lua modify arrays inside function - lua

I am trying to modify a collection of arrays inside of a variadic function. I end up working on a copy when trying to add to the arrays and they get lost after the call. Is there any way to pass values by ref in Lua?
function myfunc(...)
local args = {...}
--do work on args--
end
"do work" doesn't actually end up doing anything but it works outside the function just fine.
Obviously I could pass an array of arrays and not use ... but that kinda defeats the purpose of using ...

In Lua, you can't just choose to pass variables by reference or not. Basic types are never passed by reference (like numbers and booleans), others are always passed by reference (like tables, userdata and strings). In the case of strings this does not matter much, because they are immutable anyhow.
So either you pass your arguments you want to work on globally as strings like this:
a=2
b=3
function myfunc(...)
local args={...}
for k,v in pairs(args) do
_G[v]=_G[v]+k
end
end
myfunc('a')
print(a) -- 3
myfunc('a','b')
print(a,b) -- 4 5
Note that this only works on globals, since locals are not kept in a table.
Working with tables makes this kind of things less painful:
function myfunc(t)
for k,v in pairs(t) do
t[k]=v+k
end
end
tab1={a=2}
myfunc(tab1)
print(tab1.a) -- 3
tab2={a=2,b=3}
myfunc(tab2)
print(tab2.a,tab2.b) -- 3 5

The purpose of using ... is grouping the whole parameter list in one varible. That has little to do with the by-reference or by-value nature of the parameters.
All natural types in Lua are passed by value, with tables being the only exception.
The simplest way to do what you want is to pass an array of arrays. If the two extra characters seem like too much typing, know that you can remove the parenthesis instead:
foo({a,b,c})
foo{a,b,c} -- equivalent

Related

What is "object = {...}" in lua good for?

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.

Lua)) how to loop table of table and get a specific property?

I am really newbie in lua. I have this lua code
local gun_info = {
g_sword={rate=0.5;spd=0;dmg=1;ammo=1;};
g_pistol={rate=0.5;spd=5;dmg=1;ammo=40;};
g_knife={rate=0.8;spd=5;dmg=1;ammo=1;};
g_shuriken={rate=0.3;spd=5;dmg=1;ammo=40;};
g_bomb={rate=0.8;spd=5;dmg=1;ammo=20;};
};
I just want get values of every ammo. Other properties are no needed.
for k, v in pairs(gun_info) do
print(k, v[1], v[2], v[3], v[4], v[5])
end
this prints out whole tables but I need just value of ammos
Use comma between table variables rather than semicolon. Using semicolon is not syntactically wrong but optional in Lua. Semicolon is usually used to separate multiple statements written in single line.
You can directly access the variable ammo by indexing the key of the table
for k, v in pairs(gun_info) do
print(k, v.ammo)
end
v.ammo and v[ammo] are not same in Lua.
Note: The order in which the elements appear in traversal will not be the same as you defined and can produce different order each time. This is due to the way tables are implemented in Lua.

Difference Between Tables and Metatables in Lua

What is the difference between tables and metatables in Corona? What are the types of metatables? How and where can I use them? What is the main purpose of using tables and metatables?
Tables in Lua are the main data type you can use to create dynamic, structured data. Other languages have arrays, lists, dictionaries (key-value storage), in Lua you only have tables. The only operations you can do with a basic table is indexing and storing a value using the tab[key] syntax, i.e.:
local tab = {}
tab['key1'] = 'Hello' -- storing a value using a string key
tab.key2 = 'World' -- this is syntax sugar, equivalent to previous
print(tab.key1, tab['key2']) -- indexing, the syntax is interchangable
You cannot do anything else with basic tables, for example adding them:
local v1={x=0,y=0}
local v2={x=1,y=1}
print(v1+v2)
--> stdin:1: attempt to perform arithmetic on local 'v1' (a table value)
A metatable allows you to modify the behavior of tables, to specify what should be done when tables are added, multiplied, concatenated (..), etc. A metatable is just a table, which contains functions with special keys, also called metamethods. You can assign a metatable to a table using setmetatable(). For example:
local Vector = {} -- this will be the metatable for vectors
function Vector.__add(v1, v2) -- what to do when vectors are added
-- create a new table and assign it a Vector metatable
return setmetatable({x=v1.x+v2.x, y=v1.y+v2.y}, Vector)
end
function Vector.__tostring(v) -- how a vector should be displayed
-- this is used by tostring() and print()
return '{x=' .. v.x .. ',y=' .. v.y .. '}'
end
local v1 = setmetatable({x=1, y=2}, Vector)
local v2 = setmetatable({x=3, y=4}, Vector)
-- vectors are added and the resulting vector is printed
print(v1 + v2) --> {x=4,y=6}
If you want to understand metatables better, you should definitely read the Programming in Lua chapter on metatables.
Lua (which is the language that Corona is based on) uses metatables for different purposes.
The relevant entry in the manual is Section 2.8.
A nice tutorial can be found here or here.
A metatable is just a table like any other, but is set as metatable on another table (which I'll call a base table further on, to make a difference between the 2 tables).
A metatable can contain anything, but the special keys (starting with a double underscore) are the interesting ones. The values set to this keys in this table will be called on special occasions. Which occasion depends on which key. The most interesting are:
__index: Will be used whenever a key in the base table is looked up, but does not exist. This can either contain table, in which the key will be looked up instead, or a function, which will be passed the original table and the key. This can be used for implementing methods on tables (OOP style), for redirection, fall through cases, setting defaults, etc etc
__newindex: Will be used whenever a new key is to be assigned in a table (which was previously nil). If it's a table, the key will be assigned in that table. If it's a function, that function will be passed the original table, key and value. This can be used for controlling access to a table, preprocessing data, redirection of assignments.
__call: enables you to set a function to be called if you use eg. table().
__add,__sub,__mul,__div,__mod are used to implement binary operations,
__unm is used to implement unary operations,
__concat is used for implementing concatenation (the .. operator)
__len is used for implementing the length operator (#)
__eq,__lt,__le are used for implementing comparisons
A small thing to know when using __index & co.: in those methods, you should use rawget and rawset in order to prevent calling the metamethod each time again, causing a loop.
As a small example:
t={1,2,3} -- basetable
mt={} -- metatable
mt.__index=function(t,k)
print("__index event from "..tostring(t).." key "..k)
return "currently unavailable"
end
mt.__newindex=function(t,k,v)
print("__newindex event from "..tostring(t).." key: "..k.." value: "..v)
if type(k)=="string" then
rawset(t,k,v:reverse())
else
rawset(t,k,v)
end
end
mt.__call=function(t,...)
print("call to table "..tostring(t).." with arguments: ".. table.concat({...},','))
print("All elements of the table:")
for k,v in pairs(t) do print(k,v) end
end
setmetatable(t,mt)
t[4]="foo" -- this will run the __newindex method
print(t[5]) -- this will run the __index method
t("foo","bar")
-- Multiple fall through example:
t={}
mt={}
mt2={}
setmetatable(t,mt) -- metatable on base table
setmetatable(mt,mt2) -- second layer of metatable
mt.__index=function(t,k) print('key '..k..' not found in '..namelookup[t]) return getmetatable(t)[k] end -- tries looking nonexistant indexes up in mt.
mt2.__index=mt.__index -- function was written portably, reuse it.
t[1]='A'
mt[2]='B'
mt2[3]='C'
namelookup={[t]="t",[mt]="mt",[mt2]="mt2"}
print(t[1],t[2],t[3],t[4])
Now these are but silly examples, you can do much more complex stuff. Take a look at the examples, take a look at the relevant chapters in Programming in Lua, and experiment. And try not to get confused ;)

In Lua, is there a function that given a function, it returns its name as a string?

Sorry if this is too obvious, but I am a total newcomer to lua, and I can't find it in the reference.
Is there a NAME_OF_FUNCTION function in Lua, that given a function gives me its name so that I can index a table with it? Reason I want this is that I want to do something like this:
local M = {}
local function export(...)
for x in ...
M[NAME_OF_FUNCTION(x)] = x
end
end
local function fun1(...)
...
end
local function fun2(...)
...
end
.
.
.
export(fun1, fun2, ...)
return M
There simply is no such function. I guess there is no such function, as functions are first class citizens. So a function is just a value like any other, referenced to by variable. Hence the NAME_OF_FUNCTION function wouldn't be very useful, as the same function can have many variable pointing to it, or none.
You could emulate one for global functions, or functions in a table by looping through the table (arbitrary or _G), checking if the value equals x. If so you have found the function name.
a=function() print"fun a" end
b=function() print"fun b" end
t={
a=a,
c=b
}
function NameOfFunctionIn(fun,t) --returns the name of a function pointed to by fun in table t
for k,v in pairs(t) do
if v==fun then return k end
end
end
print(NameOfFunctionIn(a,t)) -- prints a, in t
print(NameOfFunctionIn(b,t)) -- prints c
print(NameOfFunctionIn(b,_G)) -- prints b, because b in the global table is b. Kind of a NOOP here really.
Another approach would be to wrap functions in a table, and have a metatable set up that calls the function, like this:
fun1={
fun=function(self,...)
print("Hello from "..self.name)
print("Arguments received:")
for k,v in pairs{...} do print(k,v) end
end,
name="fun1"
}
fun_mt={
__call=function(t,...)
t.fun(t,...)
end,
__tostring=function(t)
return t.name
end
}
setmetatable(fun1,fun_mt)
fun1('foo')
print(fun1) -- or print(tostring(fun1))
This will be a bit slower than using bare functions because of the metatable lookup. And it will not prevent anyone from changing the name of the function in the state, changing the name of the function in the table containing it, changing the function, etc etc, so it's not tamper proof. You could also strip the tables of just by indexing like fun1.fun which might be good if you export it as a module, but you loose the naming and other tricks you could put into the metatable.
Technically this is possible, here's an implementation of the export() function:
function export(...)
local env = getfenv(2);
local funcs = {...};
for i=1, select("#", ...) do
local func = funcs[i];
for local_index = 1, math.huge do
local local_name, local_value = debug.getlocal(2, local_index);
if not local_name then
break;
end
if local_value == func then
env[local_name] = local_value;
break;
end
end
end
return env;
end
It uses the debug API, would require some changes for Lua 5.2, and finally I don't necessarily endorse it as a good way to write modules, I'm just answering the question quite literally.
Try this:
http://pgl.yoyo.org/luai/i/tostring
tostring( x ) should hopefully be what you are looking for
If I am not wrong (and I probably will, because I actually never programmed in Lua, just read a bunch of papers and articles), internally there is already a table with function names (like locals and globals in Python), so you should be able to perform a reverse-lookup to see what key matches a function reference.
Anyway, just speculating.
But the fact is that looking at your code, you already know the name of the functions, so you are free to construct the table. If you want to be less error prone, it would be easier to use the name of the function to get the function reference (with eval or something like that) than the other way around.

Some question about "Closure" in Lua

Here's my code, I confuse the local variable 'count' in the return function(c1,c2) with memory strack and where does they store in?
function make_counter()
local count = 0
return function()
count = count + 1
return count
end
end
c1 = make_counter()
c2 = make_counter()
print(c1())--print->1
print(c1())--print->2
print(c1())--print->3
print(c2())--print->1
print(c2())--print->2
in the return function(c1,c2) with memory strack and where does they store in?
It's stored in the closure!
c1 is not a closure, it is the function returned by make_counter(). The closure is not explicitly declared anywhere. It is the combination of the function returned by make_counter() and the "free variables" of that function. See closures # Wikipedia, specifically the implementation:
Closures are typically implemented with a special data structure that contains a pointer to the function code, plus a representation of the function's lexical environment (e.g., the set of available variables and their values) at the time when the closure was created.
I'm not quite sure what you're asking exactly, but I'll try to explain how closures work.
When you do this in Lua:
function() <some Lua code> end
You are creating a value. Values are things like the number 1, the string "string", and so forth.
Values are immutable. For example, the number 1 is always the number 1. It can never be the number two. You can add 1 to 2, but that will give you a new number 3. The same goes for strings. The string "string" is a string and will always be that particular string. You can use Lua functions to take away all 'g' characters in the string, but this will create a new string "strin".
Functions are values, just like the number 1 and the string "string". Values can be stored in variables. You can store the number 1 in multiple variables. You can store the string "string" in multiple variables. And the same goes for all other kinds of values, including functions.
Functions are values, and therefore they are immutable. However, functions can contain values; these values are not immutable. It's much like tables.
The {} syntax creates a Lua table, which is a value. This table is different from every other table, even other empty tables. However, you can put different stuff in tables. This doesn't change the unique value of the table, but it does change what is stored within that table. Each time you execute {}, you get a new, unique table. So if you have the following function:
function CreateTable()
return {}
end
The following will be true:
tableA = CreateTable()
tableB = CreateTable()
if(tableA == tableB) then
print("You will never see this")
else
print("Always printed")
end
Even though both tableA and tableB are empty tables (contain the same thing), they are different tables. They may contain the same stuff, but they are different values.
The same goes for functions. Functions in Lua are often called "closures", particularly if the function has contents. Functions are given contents based on how they use variables. If a function references a local variable that is in scope at the location where that function is created (remember: the syntax function() end creates a function every time you call it), then the function will contain a reference to that local variable.
But local variables go out of scope, while the value of the function may live on (in your case, you return it). Therefore, the function's object, the closure, must contain a reference to that local variable that will cause it to continue existing until the closure itself is discarded.
Where do the values get stored? It doesn't matter; only the closure can access them (though there is a way through the C Lua API, or through the Lua Debug API). So unlike tables, where you can get at anything you want, closures can truly hide data.
Lua Closures can also be used to implement prototype-based classes and objects. Closure classes and objects behave slightly differently than normal Lua classes and their method of invocation is somewhat different:
-- closure class definition
StarShip = {}
function StarShip.new(x,y,z)
self = {}
local dx, dy, dz
local curx, cury, curz
local engine_warpnew
cur_x = x; cur_y = y; cur_z = z
function setDest(x,y,z)
dx = x; dy=y; dz=z;
end
function setSpeed(warp)
engine_warpnew = warp
end
function self.warp(x,y,z,speed)
print("warping to ",x,y,x," at warp ",speed)
setDest(x,y,z)
setSpeed(speed)
end
function self.currlocation()
return {x=cur_x, y=cur_y, z=cur_z}
end
return self
end
enterprise = StarShip.new(1,3,9)
enterprise.warp(0,0,0,10)
loc = enterprise.currlocation()
print(loc.x, loc.y, loc.z)
Produces the following output:
warping to 0 0 0 at warp 10
1 3 9
Here we define a prototype object "StarShip" as an empty table.
Then we create a constructor for the StarShip in the "new" method. The first thing it does is create a closure table called self that contains the object's methods. All methods in the closure (those defined as 'function self.') are "closed" or defined for all values accessible by the constructor. This is why it's called a closure. When the constructor is done it returns the closure object "return self".
A lot more information on closure-based objects is available here:
http://lua-users.org/wiki/ObjectOrientationClosureApproach

Resources