lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

On Sun, Sep 11, 2011 at 2:02 PM, Lorenzo Donati <> wrote:
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).

(Section 2.5)

And this:

| Otherwise, index must be the string "#", and select returns the
| total number of extra arguments it received.

(Section 5.1)

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.

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:

function f() return end
function g() return nil end

cannot be told apart using assignment:

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.

(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 nrets
  local function helper( ... )
    nrets = select( '#', ... )
    return ...

  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

Good idea! Thanks!
I'll try that and see if it helps.

-- Lorenzo

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...

  Eduardo Ochs