Table Constructors

lua-users home
wiki


[!] VersionNotice: This page seems a bit dated, relating to Lua 4 table construction issues that are now resolved in Lua 5, and it's not really clear from the scattered discussion what the problems and resolutions were. Perhaps someone can write a summary of this and identify any issues that do remain. --DavidManura

Note: Wow, with lua 4.1work4 this proposal has been adopted (well, the most relevant part at least).

I didn't even know the lua authors took notice of my proposal, so this came as a surprise - i can only say: THANKS! :-)

There is only one thing left to do, that i still think would be nice: Specify a start for a range t = {[97]="a","b","c","d","e"}

And maybe making the comma optional in some cases would be cool. (Joshua Jensen has been stirring this up again in 2/2003)


I think that the current use of ; and , in table constructors is confusing. At least it is something you cannot easily deduce from reading sample code.

Someone who sees two tables t = {1,2,3} and t2 = {x=1,y=2} and tries to intuitively combine them will fail.

i am wondering if the table constructor syntax could be improved:

currently a table constructor is seperated in 2 parts: the lfieldlist (vector-like constructor) and the ffieldlist (map-like constructor) if a constructor contains both vector-like and map-like constructor parts, they must be separated with a semicolon:

t = {1,2;x=1,y=2}

i find this not intuitive, i'd rather like to write:

t = {1,2,x=1,y=2}

or to go even further, i'd like to be able to mix the two, like this:

t = {1,2,x=1,y=2,3,4} -- equivalent to: {1,2,3,4;x=1,y=2}

t2 = {x=1,y=2;1,2,3,4;color="red"} -- equivalent to: {1,2,3,4;color="red",x=1,y=2}

and one more thing that would be nice would be to specify where a list should start: (somehow like c-enums)

t = {[97]="a","b","c","d","e"} -- equivalent to:

{[97]="a",[98]="b",[99]="c",[100]="d",[101]="e"}

to achieve both, assume that if no explicit index is given, the last numeric index + 1 should be used.

Note: this has to be a (with large lists slow) run-time calculation. [f()]="a" is perfectly valid and the compiler does not know at all what index f() will give. So what do you do with this: { [1]=1, [3]=3, n=6, 11, 22 } What indexes would 11 and 22 get? 2 and 4? Or 2 and 3? Or 4 and 5? Or 7 and 8? And what about the n? Should it be updated? It's not that easy ;-) --ET

{[1]=1, [3]=3, n=6, 11, 22} should be equivalent to {[1]=1, [3]=3, n=6, [4]=11, [5]=22} from my definition to use the last (or more specifically the last used) numeric index +1. also i'd like to ignore the messy "n" field ;)
To make it more clear, another example: {[100]=0,[10]=1,2,3} should be equivalent {[100]=0,[10]=1,[11]=2,[12]=3} - there is no complicated run-time calculation involved. just store the last used numeric index somewhere while constructing the table. --PeterPrade

for backwards compatibility, ";" could be treated equivalent to "," so all those forms would be valid:

t = {1,2,3}

t = {1;2;3}

t = {1,2;n=2}

t = {1,2,;n=2,}


What is the reason for the current syntax? well, it helps the compiler to create a more efficient bytecode:

v = {1,2,3}

results in the following, optimized code:


     1  [1]     CREATETABLE     3

     2  [1]     PUSHINT         1

     3  [1]     PUSHINT         2

     4  [1]     PUSHINT         3

     5  [1]     SETLIST         0 3

     6  [1]     SETGLOBAL       0       ; v

while

m = {[1]=1, [2]=2, [3]=3}

results in the less efficient code:


     7  [2]     CREATETABLE     3

     8  [2]     PUSHINT         1

     9  [2]     PUSHINT         1

    10  [2]     PUSHINT         2

    11  [2]     PUSHINT         2

    12  [2]     PUSHINT         3

    13  [2]     PUSHINT         3

    14  [2]     SETMAP          3

    15  [2]     SETGLOBAL       1       ; m

As we can see, if we use a lfieldlist to construct a table we get more efficient code - even if the resulting tables are exactly the same. The current table constructor syntax seems to be tailored to help the parser create the most efficient code without having to analyze the contents of the table being constructed.


Summary: i'd like to see those things changed:

Would it be hard to achieve this? I think not:

The idea to make the separator optional won't work, as this example points out: t={print "text"}

(PeterPrade)

It is redundant in the ffieldpart ({ name=value name=value ... }) of table constructors. Only the [expr]=value fields need a (leading) comma so that the [] is not made part of the previous expression. But that would give a syntax error anyway (name=val[foo]=val2)). --ET


Opinions? (for example: "don't talk about it, just code it!" or "i like the current syntax")

More Ideas?


RecentChanges · preferences
edit · history
Last edited July 7, 2007 7:25 pm GMT (diff)