~technomancy/fennel#83: 
(values) gives weird results on boolean operators

(and (values)) returns invalid Lua code.

(and true (values)) optimizes? to true, where (and true ((fn [] (values)))) returns nil. this seems like a bug with optimizing out values; i can't imagine any situation where replacing x with ((fn [] x)) should lead to a different result.

Status
RESOLVED FIXED
Submitter
~equa
Assigned to
No-one
Submitted
a month ago
Updated
a month ago
Labels
bug

~equa a month ago

(and 1 (values 2 3) 4) -> (and 1 2 3 4)?

~andreyorst a month ago*

probably

(and 1 (values 2 3) 4) -> (and 1 2 4)

edit:

huh apparently it works as expected:

>> (and true (values true true false) true true)
false

I've confused this with unpack behavior in operators

>> (and true (table.unpack [true false]) true)
true

~technomancy a month ago

(and (values)) returns invalid Lua code.

I think I have this fixed in 6ab756c.

I can't imagine any situation where replacing x with ((fn [] x)) should lead to a different result.

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.

~equa a month ago*

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.

~technomancy a month ago

which IMO means that it should emulate the same behavior as the runtime

The problem is the runtime behavior is wrong. So it's a choice between being inconsistent or being consistently wrong. Neither choice is very good. I think you can make a good argument that being consistent is better, but I'm not sure it's a good enough argument to merit changing the existing behavior.

There's a third option: you can detect a function call in the final argument and expand to an inline function which essentially reduces over all the runtime values. The problem is this puts in a significant overhead on almost every math and boolean operation even though 99% of the time it's completely unnecessary.

Basically we're forced to choose between a selection of bad options. =\

~equa a month ago

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 and clause 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?

~technomancy a month ago

Oh, yes, you're right. I was only considering the tail position. Mid-arglist there's nothing wrong with collapsing things down to one, and it should be easy to implement.

~technomancy REPORTED FIXED a month ago

Register here or Log in to comment, or comment via email.