34

I'm trying to call a function in Lua that accepts multiple 'number' arguments

function addShape(x1, y1, x2, y2 ... xn, yn)

and I have a table of values which I'd like to pass as arguments

values = {1, 1, 2, 2, 3, 3}

Is it possible to dynamically 'unpack' (I'm not sure if this is the right term) these values in the function call? Something like..

object:addShape(table.unpack(values))

Equivalent to calling:

object:addShape(1, 1, 2, 2, 3, 3)

Apologies if this is a totally obvious Lua question, but I can't for the life of me find anything on the topic.


UPDATE

unpack(values) doesn't work either (delving into the method addShape(...) and checking the type of the value passed reveals that unpackis resulting in a single string.

codinghands
  • 1,741
  • 2
  • 18
  • 31

3 Answers3

41

You want this:

object:addShape(unpack(values))

See also: http://www.lua.org/pil/5.1.html

Here's a complete example:

shape = {
  addShape = function(self, a, b, c)
    print(a)
    print(b)
    print(c)
  end
}

values = {1, 2, 3}
shape:addShape(unpack(values))
John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • I should have added, I initially tried just `unpack` but this does not work either - the type of the argument being passed becomes a single `string` – codinghands Mar 16 '14 at 06:52
  • 1
    Try doing exactly what they show in the documentation I linked. Let us know if that works or is not what you want. – John Zwinck Mar 16 '14 at 07:04
  • I've looked into the `addShape` method and checked the type of `...`. It's a `string` - the docs seem to state exactly what I want, but I don't know why `unpack`ing `values` is returning a `string` – codinghands Mar 16 '14 at 07:16
  • What version of Lua are you using? – John Zwinck Mar 16 '14 at 07:17
  • 5.2 (JNLua), though I've also tried 5.1 to no avail. – codinghands Mar 16 '14 at 07:22
  • I added a complete example, tested on Lua 5.2. – John Zwinck Mar 16 '14 at 07:41
  • There is no other way except writing your own unpack( ) or using that native functionality. Should work. – ascx Mar 16 '14 at 07:43
  • 2
    Where do you get your values array from? Bet type(values[1]) is "string". `...` has no type, but passing it to `type` is like passing the first var-arg parameter. – Deduplicator Mar 16 '14 at 15:20
  • @Deduplicator that was the exact issue - an errant rounding function returning a `string`. Derp. Thank you and @John Zwinck. – codinghands Mar 16 '14 at 21:40
  • @Nik-Lz: With such a vague statement no one can help you. The code was tested on Lua 5.2 and does work. – John Zwinck Nov 10 '17 at 00:26
  • 2
    @Nikos: just for reference, `table.unpack` [should work in Lua 5.2 and later https://stackoverflow.com/questions/25794364/lua-trouble-attempt-to-call-global-unpack-a-nil-value] – Paul D. Waite May 24 '19 at 22:25
13

Whoever comes here and has Lua version > 5.1 unpack is moved into the table library so you can use: table.unpack

For more info: https://www.lua.org/manual/5.2/manual.html

HSLM
  • 1,692
  • 10
  • 25
  • Newest version of LuaJIT (2.1.0-beta3) does not support `table.unpack` as a default, you have to use `unpack` instead or build it with `DLUAJIT_ENABLE_LUA52COMPAT`, see [here](http://luajit.org/extensions.html#lua52). – KingKevin23 Jun 01 '23 at 15:05
-7

This is not an answer about unpack, but a suggestion to use a different technique. Instead, do

function object:addShape(values)
    for i,v in ipairs(values) do 
        x,y = v.x, v.y
        ...
    end
end

function getPairs(values)
    xyPairs = {}
    for i=1,#values,2 do 
        v = {x=values[i], y=values[i+i] }
        table.insert(xyPair, v)
    end
    return xyPairs
end

values = {1, 1, 2, 2, 3, 3}
object:addShape(getPairs(values))

The amount of work to be done should be similar as unpacking and the additional processing you will have to do in addShape() to support variable number of named arguments.

Oliver
  • 27,510
  • 9
  • 72
  • 103
  • 4
    -1 for this solution. Not only do you create a new table for calling the function getPairs() but you also create a new table for every pair of values in the passed in parameter. This is exceptionally expensive compared to using unpack(). – Simon Feb 18 '15 at 17:21
  • 20
    I realized that others could learn from my mistake and Simon's comment so I'm going to leave it there as an example of what not to do :) – Oliver Nov 17 '18 at 18:51