Is there any variable in lua equivalent to extern variables in C++ ??
I want to be able to define the variables in one script and read/use those values in another.
From Scope Tutorial on lua-users wiki,
Any variable not defined as local is in the global scope. Anything in the global scope is accessible by all inner scopes.
For your question; let's say I've files one.lua and two.lua
one.lua
local x = 3
y = 17
two.lua
dofile( "one.lua" )
print( x, y )
The output shall be
nil 17
If you're still unsure if some variable will be local or global; you can use _G table for them. Like this:
_G.y = 17 -- Same as y = 17 in one.lua
They are called global variables. Any variable that is used without being declared local is global.
In other words, this is the default already. You don't have to do anything special.
Related
I have actually been wondering about this question for a long time, and I can recall reading something somewhere on the internet about loading all local variables into a table, but I could never find it again.
What I am wondering is if there is basically any way to dynamically create a local variable, similar to how you can dynamically create a global variable.
In Lua you can create dynamic global variables simply by saying:
local my_env = getfenv(1);
for i = 1, 10 do
my_env["OMG_DYNAMIC_GLOBAL_VARIABLE_"..i] = i * i;
end
But I have always wondered if there is a way to essentially do the same or a similar thing for local variables. Something like
for i = 1, 10 do
local["OMG_DYNAMIC_LOCAL_VARIABLE_"..i] = i * i;
end
would kind of be pseudo code for what I am trying to do.
As a second part to my question, I am wondering if there is any way to possibly iterate through every local variable in the current scope? I guess pseudo code for what I am trying to do would look something like:
local a = 123;
local b = 321;
LocalVars = {(local)}; --the table with the local variables in it.
for i,v in pairs(LocalVars) do print(i, v); end
I would appreciate any help regarding either part of my question.
Thanks
the table with the local variables in it
There is no table with local variables. Local variables do not exist in compiled Lua. There are simply locations on the Lua stack and/or upvalues. Even the names of local variables are lost during the compilation process.
Local variables are always static constructs of the Lua source code. They never exist within a table. If you need a non-static construct, use a table. That's what tables are for. That's (part of) why Lua globals are in a table.
I don't see the advantage of what you proposed over a regular local table except for syntactic sugar.
local locals = {}
locals.a = 123
locals.b = 321
for i,v in pairs(locals) do
print(i, v)
end
The syntax you proposed does not make the program clearer or easier to read in any way. In fact it even creates new problems. Does the following print c as well or does it not because it is in a nested local scope?
for i,v in pairs(LocalVars) do
local c = 1729
print(i, v)
end
Suppose I have the following two Lua files:
In a.lua:
local x = 5
f = dofile'b.lua'
f()
In b.lua:
local fun = function()
print(x)
end
return fun
Then if I run luajit a.lua in shell it prints nil since x cannot be seen in the function defined in b.lua. The expected printing should be 5. However if I put everything in a single file then it's exactly what I want:
In aa.lua:
local x = 5
local f = function()
print(x)
end
f()
Run luajit aa.lua it prints 5.
So why x cannot be seen in the first case?
As their name suggests, local variables are local to the chunk.
dofile() loads the chunk from another file. Since it's another chunk, it makes sense that the local variable x in the first chunk isn't seen by it.
I agree that it is somewhat unintuitive that this doesn't work.
You'd like to say, at any point in the code there is a clear set of variables that are 'visible' -- some may be local, some may be global, but there is some map that the interpreter can use to resolve names of either kind.
When you load a chunk using dofile, then it can see whatever global variables currently exist, but apparently it can't see any local variables. We know that 'dofile' is not like C/C++ inclusion macros, which would give exactly the behavior you describe for local variables, but still you might reasonably expect that this part of it would work the same.
Ultimately there's no answer but "that's just not how they specified the language". The only satisfying answer is probably along the lines 'because otherwise it would cause non-obvious problem X' or 'because then use-case Y would go slower'.
I think the best answer is that, if all names were dynamically rebound according to the scope in which they are loaded when you use loadfile / dofile, that would inhibit a lot of optimization and such when compiling chunks into bytecode. In the lua system, name resolution works like 'either it is local in this scope, and then it binds to that (known) object, or, it is a lookup in the (unique) global table.' This system is pretty simple, there are only a few options and not a lot of room for complexity.
I don't think that running byte code even keeps track of the names of local variables, it discards them after the chunk is compiled. They would have to undo that optimization if they wanted to allow dynamic name resolution at chunk loading time like you suggest.
If your question is not really why but how can I make it work anyways, then one way you can do it is, in the host script, put any local variables that you want to be visible in the environment of the script that is called. When you do this you need to split dofile into a few calls. It's slightly different in lua 5.1 vs lua 5.2.
In lua 5.1:
In a.lua:
local shared = { x = 5 }
temp = loadfile('b.lua')
setfenv(temp, shared)
f = temp()
f()
In lua 5.2:
In a.lua:
local shared = { x = 5 }
temp = loadfile('b.lua', 't', shared)
f = temp()
f()
The x variable defined in module a.lua cannot be seen from b.lua because it was declared as local. The scope of a local variable is its own module.
If you want x to be visible from b.lua, just need to declare it global. A variable is either local or global. To declare a variable as global, just simply do not declare it as local.
a.lua
x = 5
f = dofile'b.lua'
f()
b.lua
local fun = function()
print(x)
end
return fun
This will work.
Global variables live within the global namespace, which can be accessed at any given time via the _G table. When Lua cannot solve a variable, because it's not defined inside the module where is being used, Lua searches that variable in the global namespace. In conclusion, it's also possible to write b.lua as:
local fun = function()
print(_G["x"])
end
return fun
At the begining of some lua package files, sometimes there will be the line local base = _G or local base = ....
What's the benefits for doing this?
What's the differences between these two lines?
For the first question, you can refer: Why make global Lua functions local?
For your second one,
What's the differences between these two lines?
When you do local base = _G, you are assigning base to be a synonym for the global environment table. On the other hand, in the statement local base = ...; the ... refer to vararg feature of lua.
It can be shown in better detail with the following example:
local a = {...}
for k, v in pairs(a) do print(k, v) end
and then, executing it as follows:
─$ lua temp.lua some thing is passed "here within quotes"
1 some
2 thing
3 is
4 passed
5 here within quotes
As you see, ... is just a list of arguments passed to the program. Now, when you have
local base = ...
lua assigns the first argument to the variable base. All other parameters will be ignored in the above statement.
I know this is very basic question but i'm pretty much confused by the local variables & their scope in lua, for instance if i write local x=12, it means that the variable x is a local variable & it's value is 12, but instead if i write local x & in the next line x=12, does this mean the same as in previous case or x=12 is treated as a global variable?
You can think of it as two totally independent things:
local x creates a "slot" in the local scope to hold a value, i.e. a variable. This variable is named x. From that point forward, until you exit that scope, any reference to x will refer to that local x.
x = 12 puts a value into the variable x. If you've previously created a local slot named x, that's where it'll go. If there is no local x in scope, it'll go into the global scope.
local x = 12 is just a shorthand for combining these two things, creating a local variable and assigning it a value at the same time.
So yes, your two scenarios are effectively equivalent.
local x
x = 12
And
local x = 12
Do the same thing.
You only use the local keyword once per scope, so that second access of x in your example will use the local x. If you then wish to access the global x, you can use __G.x
How to define a variable(constant) in Lua and how to call it in other Lua script in Cocos2d-x?
In my way:
main.lua
local r = require("src/Square")
local constant= r:getConstant()
Square.lua
function Square:getConstant()
return 10
end
Are there any other more elegant way? Any suggestions will be appreciated.
You can make it a global variable:
constant = r:getConstant()
but the variable will not be constant. Lua does not know the concept of immutable/readonly/const variables.
There are tricks to use a Lua table's metatable to prevent the value from changing, though that requires the value to be in the table, and you can't prevent the table from being changed (ie set to nil or its metatable replaced).
Simply using a function that returns a constant value is the easier way to ensure const-ness of the value.
What I've also done in the past is to use a notation that marks constant values, for instance:
_constant = 10
local _localConstant = 11
The _ prefix denotes the variable as a constant. Alternatively an ALL-CAPS style analogue to #define macros works well if these are known constants in C/C++ or commonly known frameworks (ie DBL_EPSILON or M_PI_2). It is just a reminder for the programmer(s).
Lastly, there's the "const" table which is a global table defining some supposed-to-be constant values:
const = {thisIsTen = 10, thatIsEleven = 11}
Using the table makes it clear those are constants:
result = 100 * const.thisIsTen
If you're looking for a const(constant) value that's read-only and can not be changed, you'll need to make a function for it (Which you already have). You also have to know that lua gets returns of basic types (number, boolean, nil, string) by value not by reference (Only if you return them by creation).
Here's the replacement for your function:
square.lua
Square = {}
Square.__index = Square
local _const = 10
function Square:GetConst()
local const = _const
return const
end
-- Test function
function Square:MoveUp()
_const = _const + 2
end
return Square
main.lua
local sr = Require("src/Square")
print(sr:GetConst()) -- 10
local plus = sr:GetConst() + 4
print(sr:GetConst(), plus) -- 10 14
sr:MoveUp()
print(sr:GetConst()) -- 12
Also take a note that the Square can be changed into a local function(Recommended), so in that case there won't be any troubles with next times creation of object.