Table is both nil and not nil at the same time - lua

For some reason, when I access only my main table, it's fine, but when I try to access it using a variable, it's somehow nil?
Here's the function that's giving the error:
function parseMtl(mtlFilePath, mtlTbl) -- Parses the mtl file at mtlFIlePath
local step1 = {} -- Table to store the split lines
local mtlID = 0 -- The ID of the material
local mtlList = {} -- The list of materials
local faceColors = {} -- The returned colors of the polygons
local fC -- A test variable
contents, size = love.filesystem.read(mtlFilePath, all) -- Read the .mtl file at mtlFilePath
step1 = split(contents, "\n") -- Split the contents into step1 by the newline character
for i=1,#step1 do
if (starts(step1[i], "newmtl")) -- Create a new material
then
mtlID = mtlID + 1
mtlName = split(step1[i], "%s")[2]
table.insert(mtlList, {mtlName, mtlID})
end
if (starts(step1[i], "Kd")) -- If it's a color value, put value into the list of materials
then
R = split(step1[i], "%s")[2] * 255
G = split(step1[i], "%s")[3] * 255
B = split(step1[i], "%s")[4] * 255
table.insert(mtlList[mtlID], {R, G, B})
end
for i=1,#mtlTbl do -- Convert the mtlTbl values into 'Vertex ID, Color' format
fC = mtlList[mtlTbl[i][2]]
table.insert(faceColors, {i, fC})
end
end
return faceColors
end
The part that's doing weird stuff is the table.insert(faceColors, {i, fC}), it's somehow returning nil when I put fC in a table, when I print the fC value directly it's not nil. I have no idea why it's doing this..

Were you trying to use the return value of table.insert?
table.insert is void, so it always returns nil.
How are you accessing your color data?
The way you set up your data, you would access it with:
local faceColors = parseMtl(...)
for i = 1, #faceColors do
print(faceColors[i][2])
end

Related

How do I add a variable into my color3.fromrgb value?

local R = script.Parent.R.Text
local G = script.Parent.G.Text
local B = script.Parent.B.Text
script.Parent.ColorIndicator.BackgroundColor3 = Color3.fromRGB(R, G, B)
Ok, so how do I make this work? I'm making a Building Tools like thing that would let you customize the color, and I want it to work by using the Text value of a TextBox to change the color of the part that would be created, any help will do.
All Instances come with a GetPropertyChangedSignal function that you can utilize to update the color anytime the text changes.
-- find the UI elements
local R = script.Parent.R
local G = script.Parent.G
local B = script.Parent.B
local Indicator = script.Parent.ColorIndicator
local function clamp(minimum, value, maximum)
return math.max(minimum, math.min(value, maximum))
end
local function updateColor(newValue)
-- use pcall to safely try and update the colors
local success, result = pcall(function()
-- try to convert the text to numbers
local r = tonumber(R.Text) or 0
local g = tonumber(G.Text) or 0
local b = tonumber(B.Text) or 0
-- limit numbers to a valid range
local clampedR = clamp(0, r, 255)
local clampedG = clamp(0, g, 255)
local clampedB = clamp(0, b, 255)
-- set the color
Indicator.BackgroundColor3 = Color3.fromRGB(clampedR, clampedG, clampedB)
end)
if not success then
warn("Failed to update colorIndicator with error : ", result)
end
end
-- listen for changes on each of the text boxes
R:GetPropertyChangedSignal("Text"):Connect(updateColor)
G:GetPropertyChangedSignal("Text"):Connect(updateColor)
B:GetPropertyChangedSignal("Text"):Connect(updateColor)
There is more you could do to prevent the user from entering text that is not numbers, like checking the newValue string for non-numerical characters and removing them... but that seems beyond what you're asking here.

What does [{n,{}}] do in lua?

As you can tell I'm a beginner in lua. I am trying to understand a function I'm stuck at what the following code segment does?
It is used in the following code snippet in the last line:
function classify(txt_dir, img_dir, cls_list)
local acc = 0.0
local total = 0.0
local fea_img = {}
local fea_txt = {}
for fname in io.lines(cls_list) do
local imgpath = img_dir .. '/' .. fname .. '.t7'
local txtpath = txt_dir .. '/' .. fname .. '.t7'
fea_img[#fea_img + 1] = extract_img(imgpath)
fea_txt[#fea_txt + 1] = extract_txt(txtpath)
end
for i = 1,#fea_img do
-- loop over individual images.
for k = 1,fea_img[i]:size(1) do
local best_match = 1
local best_score = -math.huge
for j = 1,#fea_txt do
local cur_score = torch.dot(fea_img[i][{k,{}}], fea_txt[j])
From my understanding, fea_img is a lua table. Is the line fea_img[i][{k,{}}] some sort of slicing for the value for the key 'i' in the table fea_img?
I tried searching for more examples and found this being used here too (last line):
for i = 1,nsamples,batchsize do
-- indices
local lasti = math.min(i+batchsize-1,nsamples)
local m = lasti - i + 1
-- k-means step, on minibatch
local batch = x[{ {i,lasti},{} }]
Any help on this would be really appreciated. Thank you!
In lua you can access a specific index on a table in multiple ways. Like these two examples
local myValue = someTable.theIndex
-- or
local myOtherValue = someTable[2]
So the construct you see here is to access some values from a (nested) table.
Also in lua you can use anything except nil as a index, so even tables are possible.
The line
fea_img[i][{k,{}}]
Can be extended to this:
local index1 = i -- i in this case is your loop variable
local index2 = { k , { } } -- This creates a table with 2 values, the first one will be the vaule of the var k, the second one is an empty table
local value1 = fea_img[index1] -- This will get you a table
local value2 = value1[index2] -- This will get the same as: fea_img[i][{k,{}}]
Correction and Addition:
As Nicol Bolas already said in the comments: The index must be an exact match. Which means it literally has to be the same table, which is not the case for the presented code from you. Either you dropped code you thought is unnecessary or fea_img has some some kind of metatable on it.
In the case of
local k = 2
local table1 = {k, { } }
local table2 = {k, { } }
table2 and table1 do have the exact same content. But they are not the same table. Which will lead to nil always being retrieved if one is used to store data in a table and the other is used to get it back.
Syntactically, t[k] is indexing a table with a key. Normally, if there is a record in the table with the key k, its value is returned. Nothing more, nothing less.
If fea_img[i] was a normal table, {k,{}} would always return nil, since table indices are resolved based on their identity ({k,{}} is always a new table). Based on your code, I have to conclude that the elements of fea_img (i.e. what extract_img returns) are not normal tables.
In Lua, you can override the indexing operation using a metatable. If you index a value that has a metatable with __index, it will be used if there is no matching record in the table:
local t = {}
setmetatable(t, {
__index = function(t, k)
return k
end
})
print(t[{}])
This table has a metatable associated with it, which is used in the indexing operation. In this case __index returns the key, but whatever library you are using might provide more complex behaviour.
This is specific to the library you are using, not something related to the Lua syntax.

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

lua Hashtables, table index is nil?

What I'm currently trying to do is make a table of email addresses (as keys) that hold person_records (as values). Where the person_record holds 6 or so things in it. The problem I'm getting is that when I try to assign the email address as a key to a table it complains and says table index is nil... This is what I have so far:
random_record = split(line, ",")
person_record = {first_name = random_record[1], last_name = random_record[2], email_address = random_record[3], street_address = random_record[4], city = random_record[5], state = random_record[6]}
email_table[person_record.email_address] = person_record
I wrote my own split function that basically takes a line of input and pulls out the 6 comma seperated values and stores them in a table (random_record)
I get an error when I try to say email_table[person_record.email_address] = person_record.
But when I print out person_record.email_address it's NOT nil, it prints out the string I stored in it.. I'm so confused.
function split(str, pat)
local t = {} -- NOTE: use {n = 0} in Lua-5.0
local fpat = "(.-)" .. pat
local last_end = 1
local s, e, cap = str:find(fpat, 1)
while s do
if s ~= 1 or cap ~= "" then
table.insert(t,cap)
end
last_end = e+1
s, e, cap = str:find(fpat, last_end)
end
if last_end <= #str then
cap = str:sub(last_end)
table.insert(t, cap)
end
return t
end
The following code is copy and pasted from your example and runs just fine:
email_table = {}
random_record = {"first", "second", "third"}
person_record = {first_name = random_record[1], last_name = random_record[1], email_address = random_record[1]}
email_table[person_record.email_address] = person_record
So your problem is in your split function.
BTW, Lua doesn't have "hashtables". It simply has "tables" which store key/value pairs. Whether these happen to use hashes or not is an implementation detail.
It looks like you iterating over some lines that have comma-separated data.
Looking at your split function, it stops as soon as there's no more separator (,) symbols in particular line to find. So feeding it anything with less than 3 ,-separated fields (for very common example: an empty line at end of file) will produce a table that doesn't go up to [3]. Addressing any empty table value will return you a nil, so person_record.email_address will be set to nil as well on the 2nd line of your code. Then, when you attempt to use this nil stored in person_record.email_address as an index to email_table in 3rd line, you will get the exact error you've mentioned.

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