  lua-l archive

• Subject: Re: Odd behaviour with multiple return values and varargs
• From: "Eduardo Ochs" <eduardoochs@...>
• Date: Thu, 13 Sep 2007 13:39:13 -0300

```Hi Tom,

On 2007sep09, Tom Miles <Tom@creative-assembly.co.uk> wrote:
> Okay, so I'm obviously missing something with this. Can anyone explain
> the behaviour from this:
>
>   function test1() return 1, 2 end
>   function test2() return 3, 4 end
>   print(test1(), test2())   --> 1 3 4
>
> I would have expected it to output 1 2 3 4. Why doesn't it?

Let me expand your example a bit:

f  = function () return 1, 2 end
f1 = function () return 1    end
g  = function () return 3, 4 end
g1 = function () return 3    end
z  = function () return      end
n  = function () return nil  end

a, b = f1(), g1(); print(a, b)   --> 1 3
a, b = f1(), g();  print(a, b)   --> 1 3
a, b = f(),  g1(); print(a, b)   --> 1 3
a, b = f(),  g();  print(a, b)   --> 1 3
a, b = z(),  g();  print(a, b)   --> nil 3
a, b = n(),  g();  print(a, b)   --> nil 3

print(f1(), g1())     --> 1 3
print(f1(), g())      --> 1 3 4
print(f(),  g1())     --> 1 3
print(f(),  g())      --> 1 3 4
print(n(),  g())      --> nil 3 4
print(z(),  g())      --> nil 3 4
print(f(),  n())      --> 1 nil
print(f(),  z())      --> 1

Note (see the last "print") that functions in Lua can return zero
values too... If Lua had the "splicing behavior" that you were
expecting, then we would have this:

print(f(),  g())                --> 1 2 3 4  (if we had splicing)
print(f1(), g())                --> 1 3 4
print(n(),  g())                --> nil 3 4
print(z(),  g())                --> 3 4      (if we had splicing)

a, b = f(),  g();  print(a, b)  --> 1 2      (if we had splicing)
a, b = f1(), g();  print(a, b)  --> 1 3
a, b = n(),  g();  print(a, b)  --> nil 3
a, b = z(),  g();  print(a, b)  --> 3 nil    (if we had splicing)

The reference manual has an impeccably precise description of how Lua
behaves - but it does not explain the rationale. Let me quote from it:
(this is from <http://www.lua.org/manual/5.1/manual.html#2.5>,
slightly abridged) -

Both function calls and vararg expressions may result in multiple
values. If the expression is used as a statement (see §2.4.6)
(only possible for function calls), then its return list is
the expression is used as the last (or the only) element of a list
enclosed in parentheses). In all other contexts, Lua adjusts the
result list to one element, discarding all values except the first
one.

f()                -- adjusted to 0 results
g(f(), x)          -- f() is adjusted to 1 result
g(x, f())          -- g gets x plus all results from f()
a,b,c = f(), x     -- f() is adjusted to 1 result (c gets nil)

a,b,c = x, f()     -- f() is adjusted to 2 results
a,b,c = f()        -- f() is adjusted to 3 results
return f()         -- returns all results from f()
return x,y,f()     -- returns x, y, and all results from f()
{f()}              -- creates a list with all results from f()
{f(), nil}         -- f() is adjusted to 1 result

An expression enclosed in parentheses always results in only one
value. Thus, (f(x,y,z)) is always a single value, even if f
returns several values. (The value of (f(x,y,z)) is the first
value returned by f or nil if f does not return any values.)

If Lua used the splicing behaviour by default then people would have
to adjust subexpressions to one result in their programs - with "()"s
- very often... but it turned out that people don't usually need
splicing so much, so the authors of Lua decided to that it would be
better to make the comma in expressions an "adjusting to 1 result"
operator instead of a splicing operator...

Cheers,
Eduardo Ochs
http://angg.twu.net/
eduardoochs@gmail.com

P.S.: any suggestions of a good syntax for a "splicing comma"? It just
occurred to me (for Lispy reasons) that "@" could be nice -

print(f(), g())   --> 1 3 4
print(f() @ g())  --> 1 2 3 4

but I'm not going to write the patch...

```

• References: