A Lua puzzle
A conversation with Marc Bradshaw about a Lua puzzle I found myself in.
Lua 5.2.1 Copyright (C) 1994-2012 Lua.org, PUC-Rio
> function x() return 'a','b','c' end
> print(x())
a b c
> print(x(),'d')
a d
A variant of this (table.unpack
shenanigans) screwed me for about half an hour this morning. I’m sure there’s a logical explanation, but I’m not seeing it.
Could the second print be prototyping as a 2 element list and then dumping the second and third elements of the first argument?
I wondered that, though Lua doesn’t have any concept of prototypes as such. But if that’s the case, why does the first work?
Its not just print()
though - where this actually bit me was doing the equivalent of: t = { x(), 'd' }
. This exhibits the same behaviour - { x() }
expands to { 'a', 'b', 'c' }
whereas { x(), 'd' }
expands to { 'a', 'd' }
.
What happens if you have a function
y()
which returns'd'
instead of using the literal?
Interesting thought, and interesting results:
Lua 5.2.1 Copyright (C) 1994-2012 Lua.org, PUC-Rio
> function x () return 'a','b','c' end
> function y () return 'd' end
> print(x(),y())
a d
But then:
> function y () return 'd','e','f' end
> print(x(),y())
a d e f
> print(x(),y(),x())
a d a b c
So it takes the first value from each of the expanded arguments except for the last one, where it takes them all.
Interesting….
Could it be an optimisation side-effect?
…
Turns out its documented: http://www.lua.org/manual/5.2/manual.html#3.4
The why isn’t exactly clear. The only possible answer I’ve found is that allowing it would make the following unclear:
a,b,c = f(), g()
in that you don’t know whether the values you got back came from f()
or g()
. I can work around this with:
a = f()
b,c = g()
This looks like an interesting library to work around it: http://luarocks.org/repositories/rocks/#vararg
But of course I could have written something similar in C myself. That’s not quite the point.