Create local variable in Lua - lua

If I have a variable name("x" for example) stored in another variable (varname in this example) I can create a global variable via
_G[varname]=42
This is a complicated way to say
x=42
Now I want to do the same thing for local variables. Is it possible?

No, because local variables are not stored in a table, or in any structure which associates their name to them. When the lua code is compiled into bytecode, local variable names turn into numeric offsets on the lua stack.

If you really need to use a string to modify local variables, your best option is using a local table.
local localVars = {}
function setValue(varname, value)
localVars[varname] = value
end
function getValue(varname)
return localVars[varname]
end
You are not really creating and destroying local variables this way, but you get pretty close.

Related

luajit how to automatically set default metatable to every newly created table?

I have a personal project and a pure lua writed object module which provides metatable with methods filter map etc to a table , I don't want to require and setmetatable for every line local foo={}
Global Constructor
I have a personal project and a pure lua writed object module which provides metatable with methods filter, map etc to a table , I don't want to require and setmetatable for every line local foo={}.
You can avoid the need for require by just ensuring that your "object module" is always loaded first, setting global variables. I consider require to be cleaner however as it makes clear the dependencies of your files (and does not pollute the global environment).
To avoid the need for setmetatable, you can write yourself a constructor function:
local metatable = ...
function Table(t) -- NOTE: global function
return setmetatable(t, metatable)
end
then, in another file which you ensure only runs after this file was executed:
local foo = Table{}
You might want to shorten Table to T if you use this very often.
Setting a metatable for all (new) tables
Do you really want this?
First of all: You probably do not want local t = {} to set a metatable on t. This would mess with linters like Luacheck while also making your code hard to follow for everyone familiar with Lua but unfamiliar with this hack.
Setting a metatable with __index also interferes with the usage of tables as dictionaries / hash maps; users now need to use rawget / rawset to circumvent your metatable. Consider the following snippet:
local dict = { filter = "bar" }
print(dict.filter) -- "bar", as expected
print(dict.map) -- filter function - unexpected
print(rawget(dict, "map")) -- nil, as expected
It will also harm performance of every table access. Do you really want this just for some syntactic sugar?
Furthermore, if you heavily set metamethods (such as the arithmetic metamethods) even if it doesn't really make sense, you again get unexpected behavior by allowing passing tables where numbers are expected etc. Lua's partial strictness when dealing with incompatible types is what distinguishes it from JS.
How to do it
how to automatically set default metatable to every newly created table?
This is not possible in general; the proper way to set metatables is to explicitly use constructors.
debug.setmetatable, primitives & functions
Using debug.setmetatable, you can set "shared"/"common" metatables for all primitive types (boolean, number, string) as well as functions. You can not set a shared metatable for objects this way however.
Hooking global/environmental variable access
This is what koyaanisqatsi's snippet does: It catches global variable access and sets the metatable on all new table global variables. This is insufficient as it forces you to use global/environmental variables, which is both bad for performance and code quality. It will in particular not work at all for local variables such as the local foo = {} in your example. It will also not work for temporary variables in expressions (consider ({...}):filter(...)).
Debug Hooks
The following approach would be more reliable than hooking environmental variable access:
Set a debug hook that runs after every instruction.
Iterate over locals & upvalues and set the metatable for each table; perhaps remember old/new locals/upvalues/tables.
Eventually consider doing this recursively, for structures such as {{}}.
Obviously this would be awfully slow. It is very likely that there still exist many "edge cases" this doesn't catch (what about table creation in C, for instance?).
Forking Lua
The only proper solution would be to add such a feature - a default metatable for all tables - to the language by forking it and implementing this right in the function where Lua creates new tables. This is the only way this could be implemented adequately - that is, with adequate performance & reliability.
For this you can set/use the Metamethod __newindex that triggers at defining something New.
For "every newly table" the right Place is: _G
_G = setmetatable(_G,
{__index = table,
__newindex = function(tab, key, value)
print('[__newindex]:', tab, key, value)
if type(value) == 'table' then
rawset(tab, key, setmetatable(value, getmetatable(tab)))
else
rawset(tab, key, value)
end
return
end
})
--[[ Example of use:
> a = {}
table: 0xf7ed2380 a table: 0xf7ed9738
> a:insert('Hi There!')
> print(a:concat())
Hi There!
> a[#a + 1] = {}
[__newindex]: table: 0xf7ed9738 2 table: 0xf7edbe40
]]
What will not work under LuaJIT (Lua 5.1)?
__gc will not be triggered at all
table.insert({'I (Key [1]) am a string in a table'}) will not triggered by __newindex

Need to declare local functions or variables inside a local table?

In lua if I have
local table={}
table.variableA=1 -- this is local?
local table2=
{
local variable2=2 -- this is the same that above?
}
and when I declare functions inside a local table, they are all locals?
Yes, but no.
Functions aren't local, they are just values. It's variables that are local or not. For example, imagine this:
function foo_global() print 'foo' end
local foo_local = foo_global
You have two variables, one global and one local, and they both contain the same function value.
When you store a function into a table, it's neither global nor local, as it's not a variable. The table can be stored in a local variable, but that doesn't really affect the function itself, only where you can access it from.
Inside a table constructor, that is, between curly braces { } you cannot use the local keyword, because it makes no sense there.

How to fix the value of a variable LUA

I'm a little doubt, I think it is easy to solve, but I do not know ...
I'm needing to save the value of a scene to another, in a game.
For example: the player is playing, and the money variable increases, this value would stay for all scenes, which is what I want. However its value is supposedly being wiped when I enter the main menu, as if it has never existed...
Can someone tell me how to set value for all my scenes?
Are you declaring your variable as a local?
For example, is the beginning of your function similar to this?:
local gamescore = score;
If so, you'll need to remove the local, like so:
gamescore = score;
This is because the local definition only declares variables in the local block of code that it resides (i.e, it cannot be called anywhere else).
For example, if I had this function:
function = Test(score)
local sc = 0+score;
return sc;
end
The variable sc wouldn't be available anywhere else, apart from inside this function, whilst:
function = Test(score)
sc = 0+score;
return sc;
end
this sc would, as it is not local to that specific function.
Don't use local if you want your variable to be used elsewhere, but be careful that you don't overwrite it in some other function, it's easy to do, as I've done it myself a few times.

function of a required file in lua doesn't seem to be called

I am trying to use require keyword in LUA to include a file with functions, since I am new to LUA firstly I tried a simple print function:
globalfunctions.lua
local globalfunctions = {}
function printSomething()
print("OOOK")
end
return globalfunctions
then I tried to call this function writing:
local m = require "globalfunctions"
m.printSomething()
but an error occurred saying "attempt to call field printSomething (nil value)"
What I am doing wrong?
The problem is you declare a function but don't add it to your module.
To actually store the function in the module returned by require, you need to add it to the table you return at the end of your module.
globalfunctions.printSomething = printSomething
Note that globalfunctions is a deceiving name choice, since a) it's a local variable itself b) the functions it will contain will not be global either, they are contained by your module
Secondly: Ideally, to make your module behave as most people expect it, you would make the function local as to not pollute the global namespace (potentially overriding an existing variable).
You made global functions a local value, meaning it can only operate locally, try changing local to global.

Declaring Lua Functions and referencing with correct name

What is the difference between the following Lua scripts in terms of function scope. How would it effect the need to require 'calculator' in some other Lua script. And how would it be referenced in say a LuaState.getGlobal(function_name). What would be its proper function name? Also any comment on advantages/disadvantages of the declaration approaches.
A) Calculator.lua
function foo(n)
return n+1;
end
B) Calculator.lua
calc= {}
function calc.foo(n)
return n+1;
end
C) Calculator.lua
function foo(n)
return n+1;
end
function calculator()
calc = {}
calc.foo=foo
return calc
end
I don't know what it is you mean exactly by the "scope" of these scripts. Exactly what these scripts do depends on how they're being executed. You could give them a different environment, thus changing what they think of as "globals".
So, I will explain what each of these scripts does based on the assumption that you are loading them with dofile, dostring, or something of the like. That is, you're applying them to the global environment.
A)
This creates a single global variable, foo, which is a function.
B)
This creates a single global variable, calc, which is a table. This table has a single entry, with the key foo, who's value is a function.
C)
This creates two global variables. foo is a function. calculator is also a function. Each call to calculator will cause the global variable calc to be overwritten. The new value of calc will be a table that has a single entry, with the key foo, who's value is a copy of what is stored in the global variable foo.
It's hard to say what the "advantages" of method C are, since it makes no sense. It creates two functions instead of one, and that second function keeps creating new tables.
B is just a "namespace" scoped version of A. The general expectation with Lua modules is that including them will usually create some table that will contain all of the functions in that module, to avoid name conflicts with existing global state. In that regard, B may be better. But it depends mostly on what this script will be used for.
Personally, for simple shell scripts and utility scripts, I don't bother with proper module scoping. When I do make a proper module, I generally use the module Lua function.
Not exactly an answer, but a comment on semantics - in Lua, you do not declare a function, you create it. The function becomes available at the time the function(...) ... end is executed. How it is available depends on where you store it.
You have to remember that:
function myfun(foo) print('foo') end
is just syntactic sugar for:
myfun = function(foo) print('foo') end
If you do not do anything special, myfun becomes a global variable stored in the global state (accessible through _G). If you say local myfun before actually calling function myfun() end, the function (actually a closure) will be stored in the local variable and available only to the scope of the local variable.
If you use require, it just finds the file and loads it once. It doesn't do anything fancy with the module like hiding globals, etc. So if you write function foo() end in your module Calculator.lua, then calling require 'Calculator' will create a function in global foo, which you can access using LuaState.getGlobal("foo"). If you create a table of functions (step B), you have to use 2 steps:
L.getGlobal("calc") -- pushes the "calc" global (a table) to the stack
L.getField(-1, "foo") -- gets the "foo" field from the table

Resources