Two proposed changes to Serialize.lua and one to PairsByKeys

Posted by WillFa on Fri 29 Aug 2008 08:31 PM — 5 posts, 14,587 views.

USA #0
1. The assertion in save_item that Lua tables meet mushclient variable naming conventions is a false constraint, since in code you actually do 'var.myTable = serialize.save("whatever")'. It's essentially validating that the contents of the MC variable meet MC's naming standards.

2. Removing "true", and "false" from the lua_reserved_words table, since there's already logic specifically for boolean keys. Although currently, once serialized, myTable[true] = "foo" becomes myTable["true"] = "foo" when restored.

3. pairsByKeys: there's a spiffier version at http://lua-users.org/wiki/SortedIteration (alternate implementation by BobC) that handles sorting all the data types correctly in a mixed table. This completes the fix to #2.

Australia Forum Administrator #1
1. Do you mean this code:


 -- make the table constructor, and recurse to save its contents
  

      assert (string.find (name, '^[_%a][_%a%d%.%[%]" ]*$') 
              and not lua_reserved_words [name], 
              "Invalid name '" .. name .. "' for table")


Are you saying that could be omitted?

2. Yes I see what you mean about true or false, assuming you are correct about point 1.

3. I don't really see what is different about the behaviour of their algorithm and mine. Can you explain? Is it anything to do with this:

http://www.gammon.com.au/forum/bbshowpost.php?id=8698

USA #2
1. Yup. It can be omitted. You're passing a table name into the function. Why have the function assert that a valid instance of a table variable has an invalid name? It's not copying _G[tbl] to var[tbl] after all, it's returning a string that you put into a var variable and a reference to the table you named. Also, save_item is called recursively.

Table1={
 [Table2]= {
   ["*Critical hit*"] = {110,113}
  }
}

are valid lua tables, that can be serialized into strings and fed to loadstring() without issue, yet the assertion fails because it doesn't like the table name that appears in the middle of the string being put into a mushclient variable.
Why should 'var.ArbitraryVariableName = "Table1 = {} \r\n Table1[Table2]={}\r\nTable1[Table2]["*Critcal hit*"]={110,113,}\r\n"' cause an assertion? It does, currently.

2. Try it. Since it's part of lua_reserved_words it'll be saved within [""] and not just []
 t = { [true] = "Boolean Key"}
print(serialize.save("t"))
->
t = {}
  t["true"] = "Boolean Key"


3. Current pairsByKeys:
t={ 3,4,[11] = "hi", Mushclient = "the best.", zMud = "icky"}
tprint(t) ->
1=3
11="hi"   -- string sort order.
2=4
"zMud"="icky"
"Mushclient" = "the best."

t[true] = "Something."
tprint(t) ->
1=3
11="hi"  
2=4
"zMud"="icky"
"true"=nil  --- note key is not bool
"Mushclient" = "the best."

with the pairsByKeys On the Website:

tprint(t) ->
true="Something."  --still bool.
1=3
2=4
11="hi"            --numerical sort order
"Mushclient"="the best."  
"zMud"="icky" 


plus it incorporates sorting for table, thread, and userdata. Sorting all data types in one algorithm. Far more useful than just table.sort's indices, or the original or recently modified pairsByKeys that only did strings, or strings and indices.
Amended on Sat 30 Aug 2008 04:31 AM by WillFa
USA #3
final thought on 1.
Moving the assert to save() might make sense for the lua_reserved_words check. Since 'and = {}' is invalid. Having it in save_item(), which is called recursively is erroneous. There's no problem with t={} t["and"] = {} t[true]={1,2}

The regexp that enforces variable naming convention also makes sense in save() not save_item(). (Though technically you can set _G['f|o?o[b!a.r"'] = {} and Lua doesn't care)
Australia Forum Administrator #4
I have fixed up serialize as you suggested. As for PairsByKeys, I think that is a bit specialized - you are right, that if you happen to have a table with booleans and tables as keys, my PairsByKeys will not work, but the one on that site has an additional overhead for simple tables that mine will not.

I have compromised by putting a link to the wiki that you suggested, to direct people there if they really need it.