(accumulate [(x y) (values 1 2) _ (ipairs blah)] (values y x)), for example, works fine in the accumulator loop, then attempts to return
x(y)when it's done. we should either disallow multiple values (i don't see a good reason for this, but there may be some design decision somewhere) or make it work properly (making sure
valuesis emitted when the accumulator variable is a sequence)
doblock into a three-or-more clause
andstatement causes the
doblock to be evaluated earlier:
(and x (do x.y) x)` local _1_ do _1_ = x.y end return (x and _1_ and x)
i mean, i agree with you on the last part, but i'm not convinced that the runtime behavior is necessarily wrong, except for in the tail case? the bug exists for more than just that, though; the splicing occurs even in the middle of an
andclause as mentioned. i mean, we don't turn
(my-func (values 1 2) 3)into
my_func(1, 2, 3), and while "multivals are turned into single values everywhere except the last argument of a function" is a slightly weird design choice, i wouldn't call it incorrect.
i have two arguments for changing the existing behavior that i think are worthwhile, though. the first is that the quirk isn't as useful as it looks: since this edge case only happens when we can determine the exact number of values that a thing has at compile time, we can't use it to do anything particularly interesting anyway.
the second is that it's already inconsistent with the other operators:
(+ 1 (values 2 3) 4)returns 7, as it should. i understand the hypothetical of wanting to replace the operators with something that behaves like a real function, but at the very least i think it'd make sense to have them be consistent with each other in the meantime?
This is true with runtime code, but I'm not sure it holds at compile-time. The and special form has to check to see how many values it's provided, and you can't tell that ((fn  (values))) is zero at compile time; you have to run it.
which IMO means that it should emulate the same behavior as the runtime (i.e. not magically transform
(values a b)into 2 and clauses etc)
random example case: a function that used to return 2 values is inlined into a macro that ends up producing a
(values)clause. the behavior rather opaquely changes as a result.
(and 1 (values 2 3) 4)->
(and 1 2 3 4)?
>> (let a) Compile error: Compile error in unknown:1 expected binding table (let a) ^^^^^^^ * Try placing a table here in square brackets containing identifiers to bind. >> ,complete a and accumulate arg assert >> (let a) Compile error: Compile error in unknown:2 expected binding table * Try placing a table here in square brackets containing identifiers to bind.
(and (values))returns invalid Lua code.
(and true (values))optimizes? to
(and true ((fn  (values))))returns
nil. this seems like a bug with optimizing out values; i can't imagine any situation where replacing
((fn  x))should lead to a different result.
similar to pengbot's ,compile, would print generated lua output.
require-macrosis a simple assertion, but
eval-compileris actually a bit more complicated! the bug isn't in processing the form, but in that it returns the numeric result without modifying it. the compiler tries to compile that, which obviously doesn't work but also leads to the question of whether
eval-compilershould return anything at all. its main purpose is to do things without producing any output, and i haven't seen any use cases where it does output something to the source code. this probably deserves its own thread later.