@grainloom huh, in ruby a void function just returns nil:
def nnn
nil
end
# => :nnn
def voidvoid
#noop
end
# => :voidvoid
nnn # => nil
voidvoid # => nil
nnn == voidvoid # => true
@bonzoesc yuh, in Lua there is actually a stack for the return values or something
in Python, you can return multiple things but it's actually just syntax sugar for returning a tuple, whereas in Lua you are pushing things onto a stack
eg. you can do
local a, nil1, nil2 = (function()return 1 end)()
-- a == 1 and nil1 == nil and nil2 == nil
@bonzoesc and you can also ignore a few returned values, this is often used instead of result types:
loadstring("bad source code")
will return nil and an error message
loadstring("return 1")
will return a funtion
if you don't expect an error then you get nil and trying to use that will sooner or later blow up
@bonzoesc
the proper way to handle that would be
local f = assert(loadstring(source_code))
if given a false-y value, assert will call error with its second parameter
@grainloom yeah, ruby does the destructuring assignment like that (but with Arrays since no tuples)
not sure how i feel about it all, kinda neat that all these languages found different things to work for different people
@clacke @feoh you usually don't have to care about it in Lua either, even if you table.pack the results, you could still table.unpack it for another function call and its params would still be nil
printing an explicit nil return vs not printing anything in the absense of a return is probably one of the only times this comes up (but it's pretty nice to have there, because you wouldn't want functions you only run for side-effects to pollute the REPL)
@grainloom Can you explain? I ask because one of the things that threw me coming from #ruby to #python is that in Ruby you get implicit returns:
```
def return_moo()
"moo"
end
```
isn't just valid but idiomatic Ruby!
Whereas in Python doing that results in no value returned at all. Confused the CRAP out of me for the longest time!
In [1]: a = 23,
In [2]: a
Out[2]: (23,)
In [3]: a, b = 23, 42
In [4]: a
Out[4]: 23
In [5]: b
Out[5]: 42
In [6]: def f():
...: return "foo", "bar"
...:
In [7]: a, b = f()
In [8]: a
Out[8]: 'foo'
In [9]: b
Out[9]: 'bar'In [18]: zip((1, 2), ("a", "b"))
Out[18]: <zip at 0x74fa28e0c0>
In [19]: a, b = zip((1, 2), ("a", "b"))
In [20]: a
Out[20]: (1, 'a')
In [21]: b
Out[21]: (2, 'b')
In [22]: (x + 1 for x in (0, 1))
Out[22]: <generator object <genexpr> at 0x74fa3ae200>
In [23]: a, b = (x + 1 for x in (0, 1))
In [24]: a
Out[24]: 1
In [25]: b
Out[25]: 2*rest eats the rest and makes a list instead of just getting the iterator. That's a missed opportunity.In [30]: a, *b, c = (x for x in (1, 2, 3))
In [31]: a
Out[31]: 1
In [32]: b
Out[32]: [2]
In [33]: c
Out[33]: 3