What is happening when I call unpack() as lua's function arguments?
Asked Answered
T

2

7

Here is what I see:

> function test(...)
>>  for i, v in ipairs({...}) do
>>    print(v)
>>  end
>>end

-- This is expected
> test(unpack({1,2}))
1
2
-- When I mix unpack and regular arguments
-- What happened to 2?
> test(unpack({1,2}), 3)
1
3
-- What happened to 3?
> test(unpack({}), 3)

-- When I put regular args before unpack, everything is fine:
> test(1, unpack({2, 3}))
1
2
3

When I mix unpacked arguments with regular args, the result are weird. Could you explain what is happening under the hood?

Timbal answered 22/5, 2016 at 8:34 Comment(1)
Does this answer your question? Lua unpack() messing argumentsUnscathed
I
5

I'll quote the Lua reference:

Both function calls and vararg expressions can result in multiple values. If an expression is used as a statement (only possible for function calls (see §2.4.6)), then its return list is adjusted to zero elements, thus discarding all returned values. 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). In all other contexts, Lua adjusts the result list to one element, discarding all values except the first one.

As you see your unpack call is reduced to one return value as it is neither the last nor the only expression in the list of expressions you pass to test:

test(unpack({1,2}), 3)

In the other case the answer is quite simple:

test(unpack({}), 3)

The first value passed to test is nil. Therefor for i, v in ipairs({...}) do end will do nothing as your table's first value is nil as unpack({}) returns nil

ipairs (t)

Returns three values (an iterator function, the table t, and 0) so that the construction

 for i,v in ipairs(t) do body end

will iterate over the key–value pairs (1,t[1]), (2,t[2]), ..., up to the first nil value.

Ilanailangilang answered 22/5, 2016 at 9:9 Comment(0)
I
6

See explanation in Lua's manual:

If an expression is used as the last (or the only) element of a list of expressions, then no adjustment is made (unless the expression is enclosed in parentheses). In all other contexts, Lua adjusts the result list to one element, either discarding all values except the first one

You get exactly this. Unpack() returns multiple values, and list of returned elements gets adjusted down to 1 element, unless it is the last expression in test() arguments.

Integrant answered 22/5, 2016 at 9:8 Comment(0)
I
5

I'll quote the Lua reference:

Both function calls and vararg expressions can result in multiple values. If an expression is used as a statement (only possible for function calls (see §2.4.6)), then its return list is adjusted to zero elements, thus discarding all returned values. 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). In all other contexts, Lua adjusts the result list to one element, discarding all values except the first one.

As you see your unpack call is reduced to one return value as it is neither the last nor the only expression in the list of expressions you pass to test:

test(unpack({1,2}), 3)

In the other case the answer is quite simple:

test(unpack({}), 3)

The first value passed to test is nil. Therefor for i, v in ipairs({...}) do end will do nothing as your table's first value is nil as unpack({}) returns nil

ipairs (t)

Returns three values (an iterator function, the table t, and 0) so that the construction

 for i,v in ipairs(t) do body end

will iterate over the key–value pairs (1,t[1]), (2,t[2]), ..., up to the first nil value.

Ilanailangilang answered 22/5, 2016 at 9:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.