Mutable number of arguments to a function in lua?

Serp

King
Joined
Apr 1, 2015
Messages
666
Hi,

how to enter a mutable number of arguments to a function ?
Like:

Code:
array = {}  

for i = 1 , math.random(1,80) do
    array[i] = i   -- this array gets a random number of entries.
end

-- Each entry has to be one argument for the testfunction.. but I don't know how

if array[1] and not array[2] then
    testfunction(array[1])
elseif array[1] and array[2] then
    testfunction(array[1],array[2])
-- ... ... ... 
end

the problem is, that the testfunction is fix. So I'm not able to change it to handle an array itself.
The testfunction is able to accept an endless number of arguments.
 
An actual implementation of your code (up to whatever point it is that you happen to be stuck at) might lend itself to others being able to give you a more direct answer. That being said, the standard practice is to pass an array as a parameter to achieve "varargs" functionality.

Code:
varargs = {}
if array[1] and not array[2] then
    table.insert(varargs, array[1])
    testfunction(varargs)
elseif array[1] and array[2] then
    table.insert(varargs, array[1]) --note: you could set up a for loop here if needed.
    table.insert(varargs, array[2])
    testfunction(varargs)
-- ... ... ...

I know it seems redundant to be rewrapping your array entries into another array as a parameter but that's how it works out sometimes.

Also, do note that "..." or "args" (a varargs solution) is deprecated in Lua 5.2 and it's functionality is hit or miss in Civ's Lua implementation and outright fails in the LuaJIT interpreter available for download here in the Utilities section. This means you can forget anything you read about those two subjects from googling this particular topic. That doesn't mean that varargs functionality doesn't exist, simply that you have to handle varargs yourself. One common thing is to make sure that "varargs ~= {}" at the start of any function using a variable number of arguments parameter where it may ever be called with no variable arguments actually loaded.
 
Then you either have to rewrite testfunction to handle the variable args array or you have to write multiple versions of testfunction for each possible set of parameters.

edit: Do keep in mind that you don't HAVE to invoke any given function with all of it's possible parameters. Lua assumes "nil" for parameters that have not been included during calling the function. The one limitation of this is that it fills parameters left-to-right so you'd have to intentionally pass "nil" as a parameter if say you wanted to skip the first parameter but input a value for the second.
 
Then you either have to rewrite testfunction to handle the variable args array or you have to write multiple versions of testfunction for each possible set of parameters.

edit: Do keep in mind that you don't HAVE to invoke any given function with all of it's possible parameters. Lua assumes "nil" for parameters that have not been included during calling the function. The one limitation of this is that it fills parameters left-to-right so you'd have to intentionally pass "nil" as a parameter if say you wanted to skip the first parameter but input a value for the second.

I don't have access to the testfunction, it is a gamefunction. I only know what it takes (endless number of arguments), and what it does.

To be honest, it is not a function from Civilization but "The Guild 2". It is also lua script, and this game has only very very few modders, most with no such lua skills to handle such problems... that's why I asked here.

The documentation of the function looks like this:
http://www.runeforge-games.net/downloads/ScriptDocumentation_latest.html#MsgBoxNoWait

So it is a message box. E.g. the body will look like this:
"Hello %1l ! You won 2%t"
This body will use the first and the second argument, that is forwarded in Variable Argument List, to fill these % placeholders.
Although it says "Variable Argument List" an array does not work. But the form I stated above does work.

The string from the body is taken from a text database, so in fact it won't look like described above.

A call for MsgBoxNoWait could look like this:
Code:
MsgBoxNoWait("","",
        "@L_PLAYER_WON_HEAD",
        "@L_PLAYER_WON_BODY",   
       "Player","1000"
        )
The text database transforms these "@L_MEASURE_ORDERCREDIT_HEAD_+0" in the prefered language.



But you mentioned "args" and "...". It is really difficult to find anything about this via google... The Guild 2 uses a very old version of lua (2004), so maybe it is worth a try?


PS: I hope it is okay to talk here about non related Civ LUA problems =/
 
From the way it's docemented, I'd say that a varargs table is exactly what it's expecting. But, it MUST be in the 5th parameter slot.

Code:
myGuildobject = guildobject or 0
myCorenode = node or (nil?)
HeaderLabel = @L_WUG
BodyLable = @L_WUW
myArgs = {"Bob the Great", "ice cream and cheese", "much potatoes"}

MsgBoxNoWait(myGuildobject, myCorenode, HeaderLabel, BodyLabel, myArgs)

-> "Bob the Great demands ice cream and cheese! He has procured much potatoes and may be willing to trade."
 
But the problem is, testfunction is not able to handle an array.
So

array = {"a","b"}
testfunction(array)


does not work.
It has to be testfunction("a","b")
/

If this is truely the case, then use testfunction(unpack(array))

See bottom of this man page
 
Hi, I really appreciate your help !! :)

@Robert13: Unfortunatly it is really like I wrote before. I pass the argument as 5th (or 6th,7th ...) argument.
So an array as 5th argument does not work. In your example it has to look like this:
Code:
MsgBoxNoWait(myGuildobject, myCorenode, HeaderLabel, BodyLabel, "Bob the Great", "ice cream and cheese", "much potatoes")
then it works.

@whoward69:
Thank you :) Unfortunately I get this error:
Code:
attempt to call global `unpack' (a nil value)
It is very frustrating to mod anything with guild2, because alot of base functions does not work. Also all table. and ipairs functions do not work, so I had to find several workarounds (I found a function to create my own ipairs and tablegetlenght)
Do you know a workaround for this unpack problem? So maybe I can define the unpack function by myself with some basic commands?

Edit:
I don't think you know the answer of the following, but maybe it is simluar in other games and you know it :):
I don't know how to put several @L Labels into the same string. Because If I try
"Hello, @L_PLAYER, you are @L_GENDER"
I won't get the full string ingame. Instead I will get only the first Label. So this would only show the Player. Not the "Hello" and not the rest after Player.
I need to know, what I have to use to sperate the labels.

This would also solve the problem with arguments above, because I could simply switch to build my own BODY with my own inputs, without using the functions 5th,6th.. parameter.
 
Try defining unpack as this (from the page whoward linked):
Code:
function unpack (t, i)
      i = i or 1
      if t[i] ~= nil then
        return t[i], unpack(t, i + 1)
      end
    end
and then call testfunc(params, unpack(array)).
 
Try defining unpack as this (from the page whoward linked):
Code:
function unpack (t, i)
      i = i or 1
      if t[i] ~= nil then
        return t[i], unpack(t, i + 1)
      end
    end
and then call testfunc(params, unpack(array)).

aaaaah , yes it does work !!! thank you so much, and thank you whoward69! :)
 
Back
Top Bottom