This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
DannySMc's profile picture

Nested Tables Seen As Functions?

Started by DannySMc, 07 November 2014 - 11:27 AM
DannySMc #1
Posted 07 November 2014 - 12:27 PM
So I have a nested table:

{
   [test1234] = {
      [Version]=1.2.0,
      [Name]="Verinian Desktop Environment",
      [Type]="Operating System",
   },
}

Now I try to do this code:


local tab = fs.open("config/versions.lua", "r")
print(type(tab))
print(tab)

for k, v in pairs(tab) do
   print(v)
end

It keeps coming back as:

table
table: 0x024eb150
function: 0x01f50310
function: 0x025040d8
function: 0x024db070

The nested table isn't a function?
Kouksi44 #2
Posted 07 November 2014 - 12:54 PM
Well I think you have to unserialize the table after loading it from the file in order to turn it into a table you can work with ?
Now its only showing the table pointer (or whatever you call it) and maybe lua can not differ this from a function pointer.
DannySMc #3
Posted 07 November 2014 - 12:58 PM
Well I think you have to unserialize the table after loading it from the file in order to turn it into a table you can work with ?
Now its only showing the table pointer (or whatever you call it) and maybe lua can not differ this from a function pointer.
It worked in older versions using unserialize, now unserializing it will add loads of new lines and syntax that is out of place!

It as been done before!!

Does anyone know how to format that table to work?
KingofGamesYami #4
Posted 07 November 2014 - 01:09 PM
The problem here is: you are iterating through the file handle. Including file.readAll() (a function), file.readLine() (a function), and file.close() (a function)

Now, if you were iterating through file.readAll(), you'd simply get an error because it's a string.
Exerro #5
Posted 07 November 2014 - 01:17 PM
You need to read the file first, then unserialize it. You can do that like this:

local h = fs.open( file, "r" )
local content
if h then
	 content = h.readAll( )
	 h.close( )
else
	 error( "could not read file", 0 )
end
local tab = textutils.unserialize( content )
if type( tab ) ~= "table" then
	   error( "(the file format is messed up)", 0 )
end
Another problem is that the keys in the table are referring to variables, not strings. To have a string index in a table, use either of the following

{
	  key = "value";
	  ["key"] = "value";
	  [key] = "value"; -- this will look for the variable called key and use it's value, rather than the string "key"
}

Edit:
Well I think you have to unserialize the table after loading it from the file in order to turn it into a table you can work with ?
Now its only showing the table pointer (or whatever you call it) and maybe lua can not differ this from a function pointer.
It worked in older versions using unserialize, now unserializing it will add loads of new lines and syntax that is out of place!

It as been done before!!

Does anyone know how to format that table to work?
That's incorrect. Unserialize effectively loads "return " followed by the string you are trying to unserialize, and returns that. Therefore, you can unserialize any Lua value, not just tables. It's serialize that adds the extra lines, as it's trying to make it more human readable.
Edited on 07 November 2014 - 12:21 PM
DannySMc #6
Posted 07 November 2014 - 03:18 PM
You need to read the file first, then unserialize it. You can do that like this:

local h = fs.open( file, "r" )
local content
if h then
	 content = h.readAll( )
	 h.close( )
else
	 error( "could not read file", 0 )
end
local tab = textutils.unserialize( content )
if type( tab ) ~= "table" then
	   error( "(the file format is messed up)", 0 )
end
Another problem is that the keys in the table are referring to variables, not strings. To have a string index in a table, use either of the following

{
	  key = "value";
	  ["key"] = "value";
	  [key] = "value"; -- this will look for the variable called key and use it's value, rather than the string "key"
}

Edit:
Well I think you have to unserialize the table after loading it from the file in order to turn it into a table you can work with ?
Now its only showing the table pointer (or whatever you call it) and maybe lua can not differ this from a function pointer.
It worked in older versions using unserialize, now unserializing it will add loads of new lines and syntax that is out of place!

It as been done before!!

Does anyone know how to format that table to work?
That's incorrect. Unserialize effectively loads "return " followed by the string you are trying to unserialize, and returns that. Therefore, you can unserialize any Lua value, not just tables. It's serialize that adds the extra lines, as it's trying to make it more human readable.

When I unserialize it thats what it does?
Exerro #7
Posted 07 November 2014 - 03:30 PM
Unserializing will turn it from a string into a Lua value. If that string reads something like "{ }", it will turn it into a table.
DannySMc #8
Posted 07 November 2014 - 03:39 PM
Unserializing will turn it from a string into a Lua value. If that string reads something like "{ }", it will turn it into a table.

I did what you said:

local tab = fs.open("config/versions.lua", "r")
print(type(tab))
print(tab.readAll())
tab = textutils.unserialize(tab.readAll())
print(type(tab))
for k, v in pairs(tab) do
print(v)
end
print(tab["test1234"].Version)

the print(type(tab)) before for loop comes back with nil…
Exerro #9
Posted 07 November 2014 - 04:14 PM
Can I see the contents of the versions.lua file?

Edit: if it is the same as what you posted in the OP, it will error. Remember what I said about [key] using the value of the variable called key (just like you can do t to get number indexes). There is a problem with this though, if you have a key which is nil, like below, it will error.

local key = nil
local t = { [key] = 5 } -- error here, cannot have nil indexes
The same goes for if you haven't defined a variable. So, in the versions.lua file, if you haven't changed it, it will be doing "[test1234]={}" and as there is no variable called test1234 it will error. Textutils will catch this error though, and rather than returning the error message, just return nil

Edit 2: maybe this will make more sense
Edited on 07 November 2014 - 03:20 PM
DannySMc #10
Posted 07 November 2014 - 04:22 PM
Can I see the contents of the versions.lua file?

Edit: if it is the same as what you posted in the OP, it will error. Remember what I said about [key] using the value of the variable called key (just like you can do t to get number indexes). There is a problem with this though, if you have a key which is nil, like below, it will error.

local key = nil
local t = { [key] = 5 } -- error here, cannot have nil indexes
The same goes for if you haven't defined a variable. So, in the versions.lua file, if you haven't changed it, it will be doing "[test1234]={}" and as there is no variable called test1234 it will error. Textutils will catch this error though, and rather than returning the error message, just return nil

Edit 2: maybe this will make more sense



{
["test1234"] = {
  ["Version"] = 1.2,
  ["Name"] = "Verinian Desktop Environment",
  ["Type"] = "Operating System",
},
["dsgdkflg"] = {
  ["kjdsskjfg"] = "kjngjfdg",
  ["jdkkjnv"] = "idfsgnfdl",
},
}
Exerro #11
Posted 07 November 2014 - 04:25 PM
Weird, what does print( tab.readAll() ) print out? Is it the correct contents of the versions.lua file?

Try this code:
Spoiler

local h = fs.open( "config/versions.lua", "r" )
if not h then
    print "Failed to open file"
end
local content = h.readAll( )
h.close( )
print( content )
local tab = textutils.unserialize( content )
print( type( tab ) )

I doubt it but there might be a problem with calling h.readAll() twice, which would explain why you're getting the error. Storing it in a variable like above would fix that.
Edited on 07 November 2014 - 03:28 PM
DannySMc #12
Posted 07 November 2014 - 04:41 PM
This is what I get:
[attachment=1961:Capture.PNG]

I don't know why :S
MKlegoman357 #13
Posted 07 November 2014 - 04:42 PM
I doubt it but there might be a problem with calling h.readAll() twice, which would explain why you're getting the error. Storing it in a variable like above would fix that.

It is actually a problem. The file contents in ComputerCraft can only be read once per file handle. That means, when you call fileHandle.readAll() the only thing you can do next with fileHandle is to call fileHandle.close().
DannySMc #14
Posted 07 November 2014 - 04:43 PM
It works when the table is local to the file… So if I store that table and at the start just put a variable and "=" and it works then, but not when loaded….
Dragon53535 #15
Posted 07 November 2014 - 10:13 PM
Let me expand on what mklegoman is saying.

local tab = fs.open("config/versions.lua", "r")
print(type(tab))
print(tab.readAll()) --# This reads the file
tab = textutils.unserialize(tab.readAll()) --# Oh no, the file's already been read we can't read anymore. this is nil
print(type(tab))
for k, v in pairs(tab) do
print(v)
end
print(tab["test1234"].Version)
I would change it to something like this.

local tab = fs.open("config/versions.lua", "r")
print(type(tab))
tbl = textutils.unserialize(tab.readAll())
tab.close() --#This will close the file. since you can't read anymore anyways
print(type(tbl))
for k, v in pairs(tbl) do
print(v)
end
print(tbl["test1234"].Version)