huh, #Python does not distinguish `return None` from having no return at all

this is a bit weird coming from #Lua

(then again, Lua's way is also a bit weird)

@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!

@feoh yeah, Ruby copied the "every statement is an expression" thing from Scheme.
I haven't used Ruby much, so I'm not sure how its return mechanism works, but in Lua, an expression can result in an arbitary number of values, kinda like in Forth, but Python does some weird tuple packing/unpacking thing.
Usually you don't have to worry about the difference, just know that you can do
status = pcall(f)
or
status, result = pcall(f)
where only the first returned value is bound, or table.pack(pcall(f)), where everything is packed into a table.
@grainloom @feoh Python doesn't do any "sugar" or "special tuple thing" around return values, every function just returns one value and that's it.

If you don't explicitly return anything, the value is None. Comma-separated values are a tuple and that's the tuple syntax and that's it. If you return a tuple, that tuple is the return value.

People get tricked into believing that parentheses are part of the tuple syntax, but the comma is what does it. The parentheses are just often required not to interpret the comma as the argument separator, but the return statement is not a function call and has no argument separator, so a comma creates a tuple.
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'
A tuple on the left of an assignment is a destructuring assignment and takes a sequence on the right. A tuple is one possible type of sequence.
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
@clacke `first, *rest = func_that_returns_list()` is a good one that I use a lot!
@pizza_pal It's just too bad that *rest eats the rest and makes a list instead of just getting the iterator. That's a missed opportunity.
@clacke that would be cool. i think you can do stuff like that in clojure.
Oh Clojure, is there anything you won't do? πŸ™‚

Still looking for an excuse to use transducers in Scheme, now that they've been ported.
Spent last night reading a bit about Clojure destructuring assignment when I should have been doing other things. πŸ™‚