How to define variable that named by function? - lua

I need to create many variables, and I want to do declare these variable's name by function. In like this:
function DefineVariable(VariableName)
return VariableName = 123 end
What i want from the function is:
DefineVariable(weg423)
-- Result: weg423 = 123
But it was not easy as I thought... That function does not worked. I want to know how to turn it into working function.
And, could i receive an answer about this too?
a = "blahblah"
...somehow...
DefineVarByValue(a)
-- Result: blahblah = 123
Ah and one more question. how to change 'table variable' to 'string or number variable'? (i mean the 'number expected, got table' error...)

All simple types in Lua are passed by value, so your DefineVariable function gets the current value of the variable weg423 and not the name of it, which means you can't change the value of weg423 from the function.
If this is a global variable, then you can pass the name of that variable (for example, DefineVariable('weg423')) and the function can then change the value of that variable by referencing it as a key in _G or _ENV table (_G[VariableName] = whatever).
I still don't see a point in doing it this way. There is nothing wrong with using weg423 = 123.

Related

Lua - Why don't Global variables need declarations?

According to Lua's manual
Global variables do not need declarations. You simply assign a value to a global variable to create it. It is not an error to access a non-initialized variable; you just get the special value nil as the result
I think declaration is good, it makes thing more manageable. Why did Lua skip declarations for Global variables? I guess they have a good reason but I don't know why.
What if I make this mistake
-- Activation Code
function TestLoco:OnActivate()
self.MyGlobal = "ABC"; --Init the global variable
end
-- Run every tick
function TestLoco:OnTick()
self.MyGIobaI = "BCD"; --Edit the global variable at every tick, but I mistake 'I' with 'l'
end
-- Call when I click the mouse
function TestLoco:OnClick()
Debug.Log(self.MyGlobal); --This print "ABC", but It should be "BCD", what if I don't notice this?
end
Because Lua has no classes. self.MyGlobal is not a global variable, it is a field in the table passed via the self parameter. The syntax is equivalent to self["MyGlobal"]. For a "true" global variable assignment (e.g. x = 0), it is equivalent to _G["x"] = 0, where _G is the global environment table.
Since Lua has no notion of classes, the type of self is simply a table. The syntax you use for specifying a "method" is just a syntactic shortcut to this:
TestLoco.OnActivate = function(self)
self["MyGlobal"] = "ABC";
end
It's just a function that assigns a field in a table. It could be called with potentially any table, hence it cannot verify the table actually should have that field.
However, Lua offers some pretty good run-time customisable checking via metatables. If you build a table specifying the "class" of a table, you can assign a metatable to every table that checks the assignment each time if it assigns to a field that you actually "declared".

Lua - get table hex identifier

I want to know how to get the table hex id. I know that doing:
local some_var = {}
print (some_var)
the result is (for instance):
table: 0x21581c0
I want the hex without the table: string. I know that maybe some of you suggest me to make a regular expression (or something similar) to remove those chars, but I want to avoid that, and just get the 0x21581c0
Thanks
This is simpler and works for all types that are associated with pointers:
local function getId(t)
return string.format("%p", t)
end
print("string:", getId("hi"))
print("table:", getId({}))
print("userdata:", getId(io.stdin))
print("function:", getId(print))
print("number:", getId(1))
print("boolean:", getId(false))
print("nil:", getId(nil))
Result:
string: 0x0109f04638
table: 0x0109f0a270
userdata: 0x01098076c8
function: 0x0109806018
number: NULL
boolean: NULL
nil: NULL
In the standard implementation, there is the global 'print' variable that refers to a standard function that calls, through the global variable 'tostring', a standard function described here. The stanard 'tostring' function is the only way to retrieve the hexadecimal number it shows for a table.
Unfortunately, there is no configuration for either of the functions to do anything differently for all tables.
Nonetheless, there are several points for modification. You can create you own function and call that every time instead, or point either of the the global variables print or tostring to you own functions. Or, set a __tostring metamethod on each table you need tostring to return a different answer for. The advantage to this is it gets you the format you want with only one setup step. The disadvantage is that you have to set up each table.
local function simplifyTableToString(t)
local answer = tostring(t):gsub("table: ", "", 1)
local mt = getmetatable(t)
if not mt then
mt = {}
setmetatable(t, mt)
end
mt.__tostring = function() return answer end
end
local a = {}
local b = {}
print(a, b)
simplifyTableToString(a)
print(a, b)
Without complex patterns, you can just search for the first space, and grab the substring of what follows.
function get_mem_addr (object)
local str = tostring(object)
return str:sub(str:find(' ') + 1)
end
print(get_mem_addr({})) -- 0x109638
print(get_mem_addr(function () end)) -- 0x108cf8
This function will work with tables and functions, but expect errors if you pass it anything else.
Or you can use a little type checking:
function get_mem_addr (o)
return tostring(o):sub(type(o):len() + 3)
end
The table id stated by the OP is invalid in the version of Lua I am using (5.1 in Roblox). A valid ID is length 8, not 9 as in your example. Either way, just use string.sub to get the sub-string you are after.
string.sub(tostring({}), 8)
The reason is, 'table: ' is 7 characters long, so we take from index 8 through the end of the string which returns the hex value.

How to define a variable in Lua and how to call it in other Lua script in Cocos2d-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.

Variable names in table field not working

I came across a problem while writing some code up for a game. It seems I can't use variables in statements like;
local Username = "Cranavvo"
game.Players.Username:BreakJoints() -- Kills the player
And the output is telling me "No such user as 'Username'" which should be "Cranavvo".
From Lua PiL on tables
To represent records, you use the field name as an index. Lua supports
this representation by providing a.name as syntactic sugar for
a["name"].
A common mistake for beginners is to confuse a.x with a[x]. The first
form represents a["x"], that is, a table indexed by the string "x".
Therefore, when you try:
game.Players.Username:BreakJoints()
Lua interprets it as:
game["Players"]["Username"]:BreakJoints()
which ofcourse is wrong. If you want to use varying name as index for a table, use them like this:
local foo = "Cranavvo"
game.Players[foo]:BreakJoints()
But to be mentioned is that the Player class do not have a BreakJoints method, you have to get the character model with help of the .Character attribute like this:
local foo = "Cranavvo"
game.Players[foo].Character:BreakJoints()
Also to be mentioned is that if the player with that name does not exist the code will break, and also that the character can be null, in which case it also breaks. Thus you need to add some error handling. Like this:
local foo = "Cranavvo"
local Player = game.Players:findFirstChild(foo)
if Player ~= nil and Player.Character ~= nil then
Player.Character:BreakJoints()
end
The correct way to do this in roblox is this:
local Username = "Cranavvo"
local p = game.Players:FindFirstChild(Username)
if(p ~= nil) then
if(p.Character ~= nil) then
p.Character:BreakJoints()
end
end
Double check if the user really exists at the time your code gets executed.
Also it should be:
game.Players.Username:BreakJoints()
EDIT:
I misread what you wanted to do:
in
...Players.Username
lua interprets Username as a named index and does not use the Username variable declared beforehand.
If you want to access an array variable with a dynamic name you can do it like this:
game.Players[Username]:BreakJoints()
additionally in roblox you could just use the following:
game.Players:GetPlayerByID(userId):BreakJoints()
Variables are very confusing in Lua sometimes.
For example, there are global and local variables.
Local variables are variables that can be forgotten/erased after the operation ends: local x = 2
Global variables are variables that stay within the game/application unforgotten, this is good with high scores and other neat things. x = 2 (Notice there isn't a "local" statement)

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