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

Error with my API passing nil to textutils.unserialize

Started by Symmetryc, 19 April 2013 - 09:17 AM
Symmetryc #1
Posted 19 April 2013 - 11:17 AM
I think I may have found a bug with textutils…

When I was using this simple code:


os.unloadAPI("xutils")
os.loadAPI("xutils")
tScreen = xutils.init()
xutils.unload(tScreen, "abc")
tScreen = xutils.load("abc")
xutils.render(tScreen)

Using this API: http://pastebin.com/PAiYZRuZ

I got the error:
textutils:177: attempt to concatenate string and nil

[It was since resolved that this error is related to the API misbehaving, rather than textutils. Please address answers accordingly. -L]
Edited by
Hawk777 #2
Posted 19 April 2013 - 12:15 PM
Line 177 of textutils, assuming it hasn’t changed from my copy (which is a bit old), is the first line of unserialize, and would produce that error if you pass a nil value as the parameter. I suggest you find out if your h.readLine() call is returning nil first, before blaming textutils.
Dlcruz129 #3
Posted 19 April 2013 - 12:33 PM
Definitely a bug with your program. Don't post a bug if you're using your own API.
Symmetryc #4
Posted 19 April 2013 - 01:17 PM
That's what I thought at first but I looked into my code for hours and couldnt find anything. And, after all, textutils was the one that error, not my program. I could be wrong though.

Edit: Are you sure it would concatenation on the first line of the function? Hold, on let me check the code for textutils.

Edit2: Yeah it is the unsearialize parameter. I still don't see what's wrong with my API, but I should probably have this locked. Sorry for being such an idiot :/. I should've not only checked my code but also textutils. I'll have to keep looking at my code though and see what is wrong.
Lyqyd #5
Posted 19 April 2013 - 01:46 PM
Moved to Ask a Pro.
Espen #6
Posted 19 April 2013 - 02:23 PM
@Symmetryc:
You're not closing the file handles in your API functions.
I.e. you're basically first opening the file "abc" for writing, but without closing you're opening it again for reading.
The problem is, as long as you don't call flush() or close() on your file handle, nothing will have been written to the file yet
and thus your h.readLine() will return nil.

Just add an h.close() to your unload() and load() functions and try again.
Symmetryc #7
Posted 19 April 2013 - 04:28 PM
@Symmetryc:
You're not closing the file handles in your API functions.
I.e. you're basically first opening the file "abc" for writing, but without closing you're opening it again for reading.
The problem is, as long as you don't call flush() or close() on your file handle, nothing will have been written to the file yet
and thus your h.readLine() will return nil.

Just add an h.close() to your unload() and load() functions and try again.
Thank you!! I would've been looking at it for days :P/>. I hadn't realized that before because I was planning on making my programs so that I was continually after every screen update unloading my tScreen, so I thought that I shouldn't close it because it would just cause unnecessary updates just to close it but it hadn't occurred to me that I would have to close it once I end the program.

Again, sorry for being so feeble-minded not to check over textutils, I really should've done that so I could see what's happened on there :/.
Espen #8
Posted 19 April 2013 - 10:20 PM
Hey, don't beat yourself up about it, we all make mistakes.
What's important is to acknolwedge them and learn from them.

To be more specific regarding your prorgam:
You shouldn't just close the file handle at the end of your program, but every time you leave the scope where the handle was defined, because otherwise you won't be able to access the handle anymore to close it, which might be a problem if you open files within an API.
Also, everytime you want to change the mode of the handle you have to close it first.

In your specific case, I'd just do it like this in your API:
function unload(tColors, path)
  h = fs.open(path, "w")
  h.writeLine(textutils.serialize(tColors))
  h.close()  -- ADDED
end

function load(path)
  tColors = {}
  h = fs.open(path, "r")
  tColors = textutils.unserialize(h.readLine())
  h.close()  -- ADDED
  return tColors
end