[Date Prev][Date Next][Thread Prev][Thread Next]
- Subject: Re: no return value vs. nil return value(s)
- From: Eduardo Ochs <eduardoochs@...>
- Date: Sun, 11 Sep 2011 15:20:12 -0300
On Sun, Sep 11, 2011 at 2:02 PM, Lorenzo Donati <email@example.com>
Thanks, but I did read that. They explain why select returns 0. That was clear. What was not clearly defined IMHO was the semantics of the return statement.
On 11/09/2011 17.02, Florian Weimer wrote:
* Lorenzo Donati:
(1) is it safe to rely on such behaviour? I.e. is it intentional or is
it only an implementation detail that may change at any time, even
with minor releases of Lua? Lua 5.2 still complies, but haven't found
a clear reference to this behaviour in the manual.
It's a result of this:
| If an _expression_ is used as the last (or the only) element of a list
| of expressions, then no adjustment is made (unless the call is
| enclosed in parentheses).
| Otherwise, index must be the string "#", and select returns the
| total number of extra arguments it received.
The two excerpts I cited in the initial message only *hints* that a function can return no value. The manual explicitly cite the case when there is no return statement. But a statement with an empty _expression_ list is not explicitly covered. The manual says:
"Functions and chunks can return more than one value..."
which again tells nothing about the case of *no* value. The "no return value" can only be inferred by common sense, but it is not clearly defined.
Other languages are more explicit in defining what the meaning of "return" is. IIRC C/C++/Java state that the meaning is the same as assignment, but here this is of no help, since obviously it is not the same for Lua since:
cannot be told apart using assignment:
function f() return end
function g() return nil end
local x = f() --> x == nil
local x = g() --> x == nil
so it seems that only "select" has the notion of "no return value vs. nil return value".
Therefore my doubt remains about whether "return" and "return nil" are semantically different also from a language definition POV, or the behaviour detected by "select" is only a byproduct of the current implementation. Moreover, being "select" a library function and not part of the language, from a formal POV its definition and behaviour should not influence the language meaning (IIRC one could even avoid loading the base library when using the C API, so select could even be missing).
Maybe I'm missing something, but IMHO the manual is not clear about it.
Good idea! Thanks!
(2) assuming that (1) is intentional and stable, I'd like to pass a
function (call it "func") to an higher order function that will call
it many times and do different things according to whether func
returned no values instead of only nil values.
function higher( func )
local function helper( ... )
nrets = select( '#', ... )
local ret1, ret2 = helper( func() )
if nrets == 0 then
print "func returned no values"
print "func returned something:"
print( ret1, ret2 )
I think you should put your logic into the helper function itself.
The result will be a bit simpler, and you can perhaps avoid creating
I'll try that and see if it helps.
Does the code below help?
fall = function () end
ret = function () return end
retnil = function () return nil end
this = function (...) return ... end
print() --> (nothing)
print(nil) --> nil
print(nil, nil) --> nil nil
print(fall()) --> (nothing)
print(ret()) --> (nothing)
print(retnil()) --> nil
print(this()) --> (nothing)
print(this(nil)) --> nil
print(this(nil, nil)) --> nil nil
print(select("#")) --> 0
print(select("#", nil)) --> 1
print(select("#", nil, nil)) --> 2
print(select("#", fall())) --> 0
print(select("#", ret())) --> 0
print(select("#", retnil())) --> 1
print(select("#", this())) --> 0
print(select("#", this(nil))) --> 1
print(select("#", this(nil, nil))) --> 2
The language would be more complex and less elegant if "return" and
"return nil" were the same - it wouldn't be so easy to return an empty
list of results...