lua: Can I use string to use variable? - lua

I want string to use variable.
variable1 = "Hello"
a = "variable" .. 1
print(a)
but it printed variable1 (of cource),
Can I print "Hello"(variable1) using variable a?

Yes, this is exactly what tables are for - you can just rewrite your code as
local variables = {}
variables.variable1 = "Hello"
local a = "variable" .. 1
print(variables[a]) -- prints Hello
In fact, global variables (as in your example you seem to be using) are already stored in a table called _G (the global table), so in your example this would work:
variable1 = "Hello"
a = "variable" .. 1
print(_G[a])

Related

Can I set the value of a variable by using the address within DXL doors?

So what I want to do is pass a variable into an eval_ by address and then set the variable in there like so:
string str = "a"
Addr64_ addr = addr_ str
eval_("string ref = addr_ " addr "; ref = \"b\"")
print str // I want it to print b here
I realize I could evalTop_ here to make the top variable available to the eval so it can set it, but this is not the behavior that I am looking for.
So after a lot of debugging and combining different answers from the following sources:
Memory hacks 1
Memory hacks 2
I found a solution! the following code should work for basically any variable:
bool a = false
eval_("bool &a = addr_ " (addr_ (&a)) "; a = true")
print a // should print true

Append elements to a Lua table from variables / Clearing a Lua table

I make a function to parsing path name and file name from a computer directory using Lua Cheat Engine, next I want store the results in to a Lua table.
My function :
function addSongList()
load_dialog = createOpenDialog(self)
load_dialog.InitalDir = os.getenv('%USERPROFILE%')
load_dialog.Filter = 'MP3 files|*.mp3|*'
load_dialog.execute()
file = load_dialog.FileName
if file then
--- parsing path and filename
local pathN = file:match("(.*[\\/])")
local path, name = file:match('(.*\\)(.*)%.mp3')
--- test to open E:\MyMP3\mysong.mp3
print(pathN) --- result : E:\MyMP3\
print(name) --- result : mysong.mp3
end
end
local mp3Table = {}
table.insert(mp3Table,{pathN,name})
Is this correct way and correct syntax using table.insert(mp3Table,{pathN,name})
How to check if elements already added to the table by print out them?
How to clearing / empty the table ?
Thank you
1 - Inserting to the table:
table.insert(tb, value) inserts the value to de table tb. Using table.insert(mp3Table,{pathN,name}) you are dynamically creating a (sub)table and then appending to the main one.
2 - Printing the table.
As already pointed out you can just traverse the table using pairs or ipairs in order to get the elements.
I prefer ipairs in this case because the table is numerically indexed and order is guaranteed in accordance to table.insert.
The inner table must be indexed by numbers because you created it usign numeric indices.
for k, v in ipairs(mp3Table) do
print(v[1], v[2])
end
But you can also opt for a metatable which will also give you the possibility to generate a string representation for the table:
mp3Table_mt =
{
__tostring = function(self)
local ret = {}
for k, v in ipairs(self) do
table.insert(ret, v[1] .. "\t" .. v[2])
end
return table.concat(ret, "\n")
end
}
When initializing mp3Table you have to assign the metatable
local mp3Table = setmetatable({}, mp3Table_mt)
Then you can just tell Lua to print the table:
print(mp3Table)
3 - Empty/Delete the table:
Well there are two different things here. One is empty another is delete.
Lua uses garbage collection so actual deleting only occurs when there are no more references to a particular table. What you can do to tell Lua you no longer need a variable is assing nil to it. If there is no other reference to the value your variable was pointing to, the GC will clean it when it runs.
But you can empty the table without deleting it.
It may be tempting to say that mp3Table = {} "empties the table". But it does not.
What you are doing in this case is assigning a fresh new table to mp3Table variable. And if any other variable is still pointing to the old table it will no get collected and the inner values will remain untouched. If there's no such other variable, the table will be garbage collected just as if you assigned nil to mp3Table variable.
So to effectivelly empty a table you have to traverse it and set all its variables to nil.
function clearTable(tb)
for i, v in pairs(tb) do
tb[i] = nil
end
end
Specifically in the case asked, just assigning a new table to mp3Table may be enough because there are no more references to the same table. Assign nil afterwards is not necessary. What matters is if there are variables pointing to the same value. If you know what you are doing and the consequenses then no problem go ahead.
Putting it all together:
mp3Table_mt =
{
__tostring = function(self)
local ret = {}
for k, v in ipairs(self) do
table.insert(ret, v[1] .. "\t" .. v[2])
end
return table.concat(ret, "\n")
end
}
function addSongList(mp3Table)
local load_dialog = createOpenDialog(self)
load_dialog.InitalDir = os.getenv('%USERPROFILE%')
load_dialog.Filter = 'MP3 files|*.mp3|*'
load_dialog.execute()
file = load_dialog.FileName
if file then
--- parsing path and filename
local pathN = file:match("(.*[\\/])")
local path, name = file:match('(.*\\)(.*)%.mp3')
--- test to open E:\MyMP3\mysong.mp3
print(pathN) --- result : E:\MyMP3\
print(name) --- result : mysong.mp3
table.insert(mp3Table,{pathN,name})
end
return mp3Table
end
function clearTable(tb)
for i, v in pairs(tb) do
tb[i] = nil
end
end
local mp3Table = setmetatable({}, mp3Table_mt)
print(addSongList(mp3Table))
clearTable(mp3Table) -- I'm not assigning a new one. Just clearing the fields.
print(mp3Table) -- Must print nothing
1)yes
2)printing table in cycle:
for k,v in pairs(mp3Table) do
print( v.pathN, v.name)
end
3)empty table
mp3Table = {} -- clean
mp3Table = nil -- delete

Simple LZW Compression doesnt work

I wrote simple class to compress data. Here it is:
LZWCompressor = {}
function LZWCompressor.new()
local self = {}
self.mDictionary = {}
self.mDictionaryLen = 0
-- ...
self.Encode = function(sInput)
self:InitDictionary(true)
local s = ""
local ch = ""
local len = string.len(sInput)
local result = {}
local dic = self.mDictionary
local temp = 0
for i = 1, len do
ch = string.sub(sInput, i, i)
temp = s..ch
if dic[temp] then
s = temp
else
result[#result + 1] = dic[s]
self.mDictionaryLen = self.mDictionaryLen + 1
dic[temp] = self.mDictionaryLen
s = ch
end
end
result[#result + 1] = dic[s]
return result
end
-- ...
return self
end
And i run it by:
local compressor = LZWCompression.new()
local encodedData = compressor:Encode("I like LZW, but it doesnt want to compress this text.")
print("Input length:",string.len(originalString))
print("Output length:",#encodedData)
local decodedString = compressor:Decode(encodedData)
print(decodedString)
print(originalString == decodedString)
But when i finally run it by lua, it shows that interpreter expected string, not Table. That was strange thing, because I pass argument of type string. To test Lua's logs, i wrote at beggining of function:
print(typeof(sInput))
I got output "Table" and lua's error. So how to fix it? Why lua displays that string (That i have passed) is a table? I use Lua 5.3.
Issue is in definition of method Encode(), and most likely Decode() has same problem.
You create Encode() method using dot syntax: self.Encode = function(sInput),
but then you're calling it with colon syntax: compressor:Encode(data)
When you call Encode() with colon syntax, its first implicit argument will be compressor itself (table from your error), not the data.
To fix it, declare Encode() method with colon syntax: function self:Encode(sInput), or add 'self' as first argument explicitly self.Encode = function(self, sInput)
The code you provided should not run at all.
You define function LZWCompressor.new() but call CLZWCompression.new()
Inside Encode you call self:InitDictionary(true) which has not been defined.
Maybe you did not paste all relevant code here.
The reason for the error you get though is that you call compressor:Encode(sInput) which is equivalent to compressor.Encode(self, sInput). (syntactic sugar) As function parameters are not passed by name but by their position sInput inside Encode is now compressor, not your string.
Your first argument (which happens to be self, a table) is then passed to string.len which expects a string.
So you acutally call string.len(compressor) which of course results in an error.
Please make sure you know how to call and define functions and how to use self properly!

How to get variables that not declared yet but will declared soon?

How can I get variables that not declared yet?
Here are simple example:
a = b
b = 123
What I want from these 2 lines is a << 123. But obv it doesn't work.
I know the easy way to get the answer a = 123 is cut 1st line and paste it to lower than 2nd line.
But I'm in some problem. I need some function like 'WillDeclaredVar()' that I can use in like this:
a = WillDeclaredVar(b)
sheepCount = 123
b = sheepCount
print(a)
so I can get the answer '123'.
Or there are any built-in functions that will allows me to do similar thing?
===
I think the link given by timrau is not telling my case. the key point is how to get Variables 'that not declared yet'.
===
Adding actual Code:
triggerCount = 0 -- Counting number of 'Trigger' function
local Trigger = function (t)
triggerCount = triggerCount + 1
return Trigger (t)
end
-- following Triggers are same as while statement.
-- following Triggers doing: Add 1 MarineCount until get 64000 MarineCount
Trigger { -- Here the Trigger function. Now triggerCount = 1.
players = {P1}
actions = {
SetDeaths(P1, Add, 1, "Terran Marine")
},
flag = {preserved},
}
Portal(LoopStart);
-- function Portal(VariableName) returns VariableName = triggerCount. So LoopStart = 1.
Trigger { -- Now triggerCount = 2.
players = {P1}
actions = {
LinkList(LoopEnd, LoopStart);
-- function LinkList(From, To) changes 'From' Trigger's next pointer to the 'To' Trigger.
-- But now the problem happens. Because 'LoopEnd' is not declared yet.
},
flag = {preserved},
}
Trigger { -- Now triggerCount = 3.
players = {P1}
conditions = {
Deaths(P1, Exactly, 64000, "Terran Marine");
}
actions = {
_LinkList(LoopEnd);
-- Reset LoopEnd's next pointer(= LoopEscape) if MarineCount hits 64000
},
flag = {preserved},
}
Portal(LoopEnd); -- LoopEnd = 3.
Changing Order of Triggers will break the Trigger logic(while statement).
All i want is get easy to coding. To put in bluntly, I don't need to solve this problem(get undeclared var). I can imagine a few ways to avoid it. But if i using these ways then the coding work will be very complicated and the difficulty of coding will increases greatly. The difficulty made me stop coding in recent months.
How can I get variables that not declared yet?
Short of time travel, you can't.
Your example code doesn't explain the motivation for the question, because this:
a = WillDeclaredVar(b)
sheepCount = 123
b = sheepCount
print(a)
Can trivially be rearranged into this:
sheepCount = 123
b = sheepCount
a = WillDeclaredVar(b)
print(a)
It would be easier to answer your question if you showed the actual problem you're trying to solve (to avoid an XY problem).
However, as stated there are few things we can note.
First, you need to distinguish between declaring a variable and giving it a value. In Lua you can say:
local b
To declare b as a local variable, which presumably will make a slot for it in the stack frame and let you bind closures to it, before you give it a value. However, the line:
a = WillDeclaredVar(b)
Will pass WillDeclaredVar the value that b currently has, and there's no way for a to change retroactively as a result of b being assigned a new value. That's simply not going to happen, ever. Neither a nor WillDeclaredVar are even aware that b exists, they are receive the value it contains at the point of call.
You could however bind the variable b to a closure which will fetch b's current value when needed.
-- declare b before giving it a value, aka "forward reference"
local b
a = function() return b end
sheepCount = 123
b = sheepCount
print(a()) -- call a to get b's current value
Another way to do that would be to make b a global variable, which is really just a key into your environment table, so you could say:
a = WillDeclaredVar('b')
And have a be some object that can fetch the current value of __ENV['b'] when required.
However, neither of these will support this syntax:
print(a)
a needs to be a function, something that looks up the value of b when needed rather than simply holding a previously computed value. You could do it in this particular instance (i.e. a needs to be convertable to a string), by creating a proxy object that implements __tostring.
function WillDeclaredVar(variableName)
local proxy = { environment = _ENV or _G, variableName = variableName }
return setmetatable(proxy, {
__tostring = function(proxy)
return proxy.environment[proxy.variableName]
end
})
end
-- a will compute a value based on the current value of b when needed
a = WillDeclaredVar('b')
sheepCount = 123
b = sheepCount
print(a)
Output:
123
To make var1 be a reference for var2 write var1 = ReferenceF or var2 (please note a space inside "ReferenceFor"!)
do
local values, references, reference_flag = {}, {}
setmetatable(_G, {
__index = function (_, name)
if name == 'ReferenceF' then
reference_flag = true
elseif reference_flag then
reference_flag = false
return {[references] = name}
elseif references[name] then
return _G[references[name]]
else
return values[name]
end
end,
__newindex = function (_, name, val)
if type(val) == 'table' and val[references] then
references[name] = val[references]
else
values[name] = val
end
end
})
end
a = ReferenceF or b -- a is Reference For b
b = ReferenceF or c -- b is Reference For c
sheepCount = 123
c = sheepCount
print(a, b, c) --> 123 123 123

How Lua tables work

I am starting to learn Lua from Programming in Lua (2nd edition)
I didn't understand the following in the book. Its very vaguely explained.
a.) w={x=0,y=0,label="console"}
b.) x={math.sin(0),math.sin(1),math.sin(2)}
c.) w[1]="another field"
d.) x.f=w
e.) print (w["x"])
f.) print (w[1])
g.) print x.f[1]
When I do print(w[1]) after a.), why doesn't it print x=0
What does c.) do?
What is the difference between e.) and print (w.x)?
What is the role of b.) and g.)?
You have to realize that this:
t = {3, 4, "eggplant"}
is the same as this:
t = {}
t[1] = 3
t[2] = 4
t[3] = "eggplant"
And that this:
t = {x = 0, y = 2}
is the same as this:
t = {}
t["x"] = 0
t["y"] = 2
Or this:
t = {}
t.x = 0
t.y = 2
In Lua, tables are not just lists, they are associative arrays.
When you print w[1], then what really matters is line c.) In fact, w[1] is not defined at all until line c.).
There is no difference between e.) and print (w.x).
b.) creates a new table named x which is separate from w.
d.) places a reference to w inside of x. (NOTE: It does not actually make a copy of w, just a reference. If you've ever worked with pointers, it's similar.)
g.) Can be broken up in two parts. First we get x.f which is just another way to refer to w because of line d.). Then we look up the first element of that table, which is "another field" because of line c.)
There's another way of creating keys in in-line table declarations.
x = {["1st key has spaces!"] = 1}
The advantage here is that you can have keys with spaces and any extended ASCII character.
In fact, a key can be literally anything, even an instanced object.
function Example()
--example function
end
x = {[Example] = "A function."}
Any variable or value or data can go into the square brackets to work as a key. The same goes with the value.
Practically, this can replace features like the in keyword in python, as you can index the table by values to check if they are there.
Getting a value at an undefined part of the table will not cause an error. It will just give you nil. The same goes for using undefined variables.
local w = {
--[1] = "another field"; -- will be set this value
--["1"] = nil; -- not save to this place, different with some other language
x = 0;
y = 0;
label = "console";
}
local x = {
math.sin(0);
math.sin(1);
math.sin(2);
}
w[1] = "another field" --
x.f = w
print (w["x"])
-- because x.f = w
-- x.f and w point one talbe address
-- so value of (x.f)[1] and w[1] and x.f[1] is equal
print (w[1])
print ((x.f)[1])
print (x.f[1])
-- print (x.f)[1] this not follows lua syntax
-- only a function's has one param and type of is a string
-- you can use print "xxxx"
-- so you print x.f[1] will occuur error
-- in table you can use any lua internal type 's value to be a key
-- just like
local t_key = {v=123}
local f_key = function () print("f123") end
local t = {}
t[t_key] = 1
t[f_key] = 2
-- then t' key actualy like use t_key/f_key 's handle
-- when you user t[{}] = 123,
-- value 123 related to this no name table {} 's handle

Resources