I'm using a lua script to get a ZINTERSTORE result. What I want is to be able to give lua a dynamic number of zsets in the call such that:
redis.pcall('ZINTERSTORE', result, n, keys[1], keys[2], keys[3], keys[4], keys[5], 'AGGREGATE', 'MAX')
becomes something like:
redis.pcall('ZINTERSTORE', result, n, dynamic_key_list, 'AGGREGATE', 'MAX')
Lua's table.getn function lets me get the size n. Problem here is that if dynamic_key_list is a list, then redis cries loud and early with:
Lua redis() command arguments must be strings or integers
I've seen this possible solution but I don't want to iterate over the table and do the redis call every time, since I could potentially have 10-15 keys and it is an overhead I can't afford. Is there another way?
In order to pass a lua array/table to a function that takes variable parameters, you need the unpack function.
-- put all arguments of redis.pcall into a lua array/table
local args = {'ZINTERSTORE', result, n}
for i, v in ipairs(dynamic_key_list) do
table.insert(args, v)
end
table.insert(args, 'AGGREGATE')
table.insert(args, 'MAX')
-- unpack the table and pass to redis.pcall
redis.pcall(unpack(args))
Related
Lua will write the code of a function out as bytes using string.dump, but warns that this does not work if there are any upvalues. Various snippets online describe hacking around this with debug. It looks like 'closed over variables' are called 'upvalues', which seems clear enough. Code is not data etc.
I'd like to serialise functions and don't need them to have any upvalues. The serialised function can take a table as an argument that gets serialised separately.
How do I detect attempts to pass closures to string.dump, before calling the broken result later?
Current thought is debug.getupvalue at index 1 and treat nil as meaning function, as opposed to closure, but I'd rather not call into the debug interface if there's an alternative.
Thanks!
Even with debug library it's very difficult to say whether a function has a non-trivial upvalue.
"Non-trivial" means "upvalue except _ENV".
When debug info is stripped from your program, all upvalues look almost the same :-)
local function test()
local function f1()
-- usual function without upvalues (except _ENV for accessing globals)
print("Hello")
end
local upv = {}
local function f2()
-- this function does have an upvalue
upv[#upv+1] = ""
end
-- display first upvalues
print(debug.getupvalue (f1, 1))
print(debug.getupvalue (f2, 1))
end
test()
local test_stripped = load(string.dump(test, true))
test_stripped()
Output:
_ENV table: 00000242bf521a80 -- test f1
upv table: 00000242bf529490 -- test f2
(no name) table: 00000242bf521a80 -- test_stripped f1
(no name) table: 00000242bf528e90 -- test_stripped f2
The first two lines of the output are printed by test(), the last two lines by test_stripped().
As you see, inside test_stripped functions f1 and f2 are almost undistinguishable.
Programming beginner here learning Lua. I always see this function in example code mostly in a for loop that goes through an array. I dont actually understand what it does and why I should use it. It seems I make similar for loops a lot that do almost the same thing but i never use pairs() or ipairs()
From the Lua 5.4 Reference manual:
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 absent index.
pairs (t)
If t has a metamethod __pairs, calls it with t as argument and returns
the first three results from the call.
Otherwise, returns three values: the next function, the table t, and
nil, so that the construction
for k,v in pairs(t) do body end
will iterate over all key–value pairs of table t.
https://www.lua.org/manual/5.4/manual.html#pdf-ipairs
https://www.lua.org/manual/5.4/manual.html#pdf-pairs
I recently read about lua and addons for the game "World of Warcraft". Since the interface language for addons is lua and I want to learn a new language, I thought this was a good idea.
But there is this one thing I can't get to know. In almost every addon there is this line on the top which looks for me like a constructor that creates a object on which member I can have access to. This line goes something like this:
object = {...}
I know that if a function returns several values (which is IMHO one huge plus for lua) and I don't want to store them seperatly in several values, I can just write
myArray = {SomeFunction()}
where myArray is now a table that contains the values and I can access the values by indexing it (myArray[4]). Since the elements are not explicitly typed because only the values themselfe hold their type, this is fine for lua. I also know that "..." can be used for a parameter array in a function for the case that the function does not know how many parameter it gets when called (like String[] args in java). But what in gods name is this "curly bracket - dot, dot, dot - curly bracket" used for???
You've already said all there is to it in your question:
{...} is really just a combination of the two behaviors you described: It creates a table containing all the arguments, so
function foo(a, b, ...)
return {...}
end
foo(1, 2, 3, 4, 5) --> {3, 4, 5}
Basically, ... is just a normal expression, just like a function call that returns multiple values. The following two expressions work in the exact same way:
local a, b, c = ...
local d, e, f = some_function()
Keep in mind though that this has some performance implications, so maybe don't use it in a function that gets called like 1000 times a second ;)
EDIT:
Note that this really doesn't apply just to "functions". Functions are actually more of a syntax feature than anything else. Under the hood, Lua only knows of chunks, which are what both functions and .lua files get turned into. So, if you run a Lua script, the entire script gets turned into a chunk and is therefore no different than a function.
In terms of code, the difference is that with a function you can specify names for its arguments outside of its code, whereas with a file you're already at the outermost level of code; there's no "outside" a file.
Luckily, all Lua files, when they're loaded as a chunk, are automatically variadic, meaning they get the ... to access their argument list.
When you call a file like lua script.lua foo bar, inside script.lua, ... will actually contain the two arguments "foo" and "bar", so that's also a convenient way to access arguments when using Lua for standalone scripts.
In your example, it's actually quite similar. Most likely, somewhere else your script gets loaded with load(), which returns a function that you can call—and, you guessed it, pass arguments to.
Imagine the following situation:
function foo(a, b)
print(b)
print(a)
end
foo('hello', 'world')
This is almost equivalent to
function foo(...)
local a, b = ...
print(b)
print(a)
end
foo('hello', 'world')
Which is 100% (Except maybe in performance) equivalent to
-- Note that [[ string ]] is just a convenient syntax for multiline "strings"
foo = load([[
local a, b = ...
print(b)
print(a)
]])
foo('hello', 'world')
From the Lua 5.1 Reference manual then {...} means the arguments passed to the program. In your case those are probably the arguments passed from the game to the addon.
You can see references to this in this question and this thread.
Put the following text at the start of the file:
local args = {...}
for __, arg in ipairs(args) do
print(arg)
end
And it reveals that:
args[1] is the name of the addon
args[2] is a (empty) table passed by reference to all files in the same addon
Information inserted to args[2] is therefore available to different files.
In the Lua command line, when I pass arguments to a script like this:
lua myscript.lua a b c d
I can read the name of my script and arguments from the global arg table. arg[0] contains the script name, arg[1] - arg[#arg] contain the remaining arguments. What's odd about this is table is that it has a value at index 0, unlike every other Lua array which starts indexing at 1. This means that when iterating over it like this:
for i,v in ipairs(arg) do print(i, v) end
the output only considers index 1-4, and does not print the script name. Also #arg evaluates to 4, not 5.
Is there any good reason for this decision? It initially took me aback, and I had to verify that the manual wasn't mistaken.
Asking why certain design decisions were made is always tricky because only the creator of the language can really answer. I guess it was chosen such that you can iterate over the arguments using ipairs and don't have to handle the first one special because it's the script name and not an argument.
#arg is meaningless anyway because it counts only the number of elements in the consecutive array section but the zeroth and negative indices are stored in the hashmap section. To obtain the actual number of elements use
local n = 0
for _ in pairs(arg) do
n = n + 1
end
At least it is documented in Programming in Lua:
A main script can retrieve its arguments in the global variable arg. In a call like
prompt> lua script a b c
lua creates the table arg with all the command-line arguments, before running the script. The script name goes into index 0; its first argument (a in the example), goes to index 1, and so on. Eventual options go to negative indices, as they appear before the script. For instance, in the call
prompt> lua -e "sin=math.sin" script a b
lua collects the arguments as follows:
arg[-3] = "lua"
arg[-2] = "-e"
arg[-1] = "sin=math.sin"
arg[0] = "script"
arg[1] = "a"
arg[2] = "b"
More often than not, the script only uses the positive indices (arg[1] and arg[2], in the example).
arg in Lua mimics argv in C: arg[0] contains the name of the script just like argv[0] contains the name of the program.
This does not contradict 1-based arrays in Lua, since the arguments to the script are the more important data. The name of the script is seldom used.
Is it possibly to dump the Lua table including function arguments?
If so, how can I do it?
I have managed to dump tables and function with addresses, but I haven't been able to figure out a way to get function args, i have tried different methods, but no luck.
So I want to receive them truth dumping tables and function plus args of the function.
Output should be something like this: Function JumpHigh(Player, height)
I don't know if it is even possible, but would be very handy.
Table only stores values.
If there's function stored in a table, then it's just a function body, there's no arguments. If arguments were applied, table would store only final result of that call.
Maybe you're talking about closure - function returned from other function, capturing some arguments from a top level function in a lexical closure? Then see debug.getupvalue() function to check closure's content.
Is this something what you're asking?
local function do_some_action(x,y)
return function()
print(x,y)
end
end
local t = {
func = do_some_action(123,478)
}
-- only function value printed
print "Table content:"
for k,v in pairs(t) do
print(k,v)
end
-- list function's upvalues, where captured arguments may be stored
print "Function's upvalues"
local i = 0
repeat
i = i + 1
local name, val = debug.getupvalue(t.func, i)
if name then
print(name, val)
end
until not name
Note that upvalues stored is not necessary an argument to a toplevel function. It might be some local variable, storing precomputed value for the inner function.
Also note that if script was precompiled into Lua bytecode with stripping debug info, then you won't get upvalues' names, those will be empty.