Unpack and tables

Hi! I have one problem here. I want to unpack 2 tables of vec3 into a mesh. It does’nt give me any errors, but when I draw it nothing shows up. Here is the code:

m.vertices=(unpack(s.vertices),unpack(c.vertices))

If you run this code you will see why it doesn’t work

t1 ={"a","b","c"}
    t2={"A","B","C"}
    t3={unpack(t1),unpack(t2)}
    for k,v in pairs(t3) do
        print(v)
    end

A workaround is this. it is slower and could be optimized

t1 ={"a","b","c"}
    t2={"A","B","C"}
    t3={unpack(t1)}
    for k,v in pairs(t2) do
        table.insert(t3,v)
    end
    for k,v in pairs(t3) do
        print(v)
    end

@coder nice finding! This is surprising.

I’m not sure why though

If you do (unpack(a),unpack(b)) it treats both the unpack functions as seperate and that means you’re trying to pass two objects to the vertices value where it only takes one. This is my understanding anyway.

The short of it is, if you have a sequence of calls to unpack(), only the last one will actually have all of it’s values unpacked; the others will only unpack the first value.

Here are 3 cases:

-- pass 2 unpacks as args to a function call
local t1 = {1, 2, 3}
local t2 = {4, 5, 6}
print(unpack(t1), unpack(t2))

prints: 1, 4, 5, 6

-- 2 unpacks in a multi-variable assignment
local t1 = {1, 2, 3}
local t2 = {4, 5, 6}
local a, b, c, d, e, f = unpack(t1), unpack(t2)
print(a, b, c, d, e, f)

would print: 1, 4, 5, 6, nil, nil

--returning multiple variables from a function:
local function doStuff()
    local t1 = {1, 2, 3}
    local t2 = {4, 5, 6}
    return unpack(t1), unpack(t2)
end

print(doStuff())

would print: 1, 4, 5, 6

Note that this doesn’t only apply to unpack(), but any function that returns multiple values.

@toadkick, that’s interesting I had never noticed this. Any idea why it is so?

@JakAttak: Take this (hopefully) instructive example:

x, y, z = foo(), 20, 30

When you write an expression like that, you need to be able to reason about which values on the right side of the expression will be assigned to which variables on the left. In this example, let’s say foo() returns a single value, 10. The results of x, y, z would be 10, 20, 30. Pretty simple, and exactly what we’d expect.

But now, let’s say foo() sometimes returns 2 values: 100 and 200. What do you expect x, y, and z to be after the expression? The language designers had to make a choice here. One possibility was:

x, y, z = 100, 200, 20

Unfortunately, since we (nor Lua) can guarantee how many results a function may return, it would make it impossible for us to reason about what values would actually end up being assigned to y and z, and thus impossible to write correct code. Let’s look at the other possibility:

x, y, z = 100, 20, 30  

Still a little strange, but at least now we can rest assured that y and z will be assigned the values we intended. So, this is the option they chose.

I recommend giving http://www.lua.org/pil/5.1.html a read if you still have a hard time understanding this (heck, even if you don’t!). Really, the whole PiL is quite informative :slight_smile:

@toadkick, yes that is what I figured. I guess it makes sense. And, you can avoid the problem by doing something like this:

x, y = foo()
z, x = foo2()