Why are table literals handled differently than table references in Lua?

Here is the Lua 5.2.2 decryption showing the declaration and indexing of the table:

> mylist = {'foo', 'bar'} > print(mylist[1]) foo 

Why is the expression not legal?

 > print({'foo', 'bar'}[1]) stdin:1: ')' expected near '[' 

I canโ€™t think of any other language where a literal cannot be replaced by a reference (except, of course, when lvalue is required).

FWIW, enclosing a table literal in parentheses, makes the statement legal:

 > print(({'foo', 'bar'})[1]) foo 
+6
source share
2 answers

This is also due to the fact that in Lua this syntax is valid:

 myfunc { 1, 2, 3 } 

and this is equivalent to:

 myfunc( { 1, 2, 3 } ) 

Therefore, an expression such as:

 myfunc { 1, 2, 3 } [2] 

analyzed as:

 myfunc( { 1, 2, 3 } )[2] 

therefore, the function call is first computed, then indexing is performed.

If {1,2,3}[2] can be analyzed as a valid indexing operation, this can lead to ambiguity in the previous expression, which will require more attention. The Lua team decided to quickly make the Lua bytecode compiler, making it a single-skip compiler, so it scans the source code only once with minimal viewing. This message to the lua mailing list from Roberto Hierasulsky (Lua lead developer) points in that direction.

The same problem exists for string literals and method calls. This is not true:

 "my literal":sub(1) 

but this is true:

 ("my literal"):sub(1) 

Again, Lua allows this:

 func "my literal" 

equivalent to this:

 func( "my literal" ) 
+10
source

According to the grammar defined here , the reason the version with the unconverted version is invalid but enclosed in brackets is because the syntax tree takes a different path and expects closing brackets ) because there should not be another character in this context.

In the first case:

 functioncall ::= prefixexp args | prefixexp `:ยด Name args prefixexp => prefixexp ::= var | functioncall | `(ยด exp `)ยด var -> print THEREFORE prefixexp -> print args => args ::= `(ยด [explist] `)ยด | tableconstructor | String match '(' explist => explist ::= {exp `,ยด} exp exp => exp ::= nil | false | true | Number | String | `...ยด | function | prefixexp | tableconstructor | exp binop exp | unop exp tableconstructor => explist-> {'foo','bar'} THEREFORE explist = {'foo','bar'} match ')' ERROR!!! found '[' expected ')' 

On the other hand, with parentheses:

 functioncall ::= prefixexp args | prefixexp `:ยด Name args prefixexp => prefixexp ::= var | functioncall | `(ยด exp `)ยด var -> print THEREFORE prefixexp -> print args => args ::= `(ยด [explist] `)ยด | tableconstructor | String match '(' explist => explist ::= {exp `,ยด} exp exp => exp ::= nil | false | true | Number | String | `...ยด | function | prefixexp | tableconstructor | exp binop exp | unop exp prefixexp => prefixexp ::= var | functioncall | `(ยด exp `)ยด var => var ::= Name | prefixexp `[ยด exp `]ยด | prefixexp `.ยด Name prefixexp => prefixexp ::= var | functioncall | `(ยด exp `)ยด match '(' exp => exp ::= nil | false | true | Number | String | `...ยด | function | prefixexp | tableconstructor | exp binop exp | unop exp tableconstructor => THEREFORE exp = {'foo','bar'} match ')' THEREFORE prefixexp = ({'foo','bar'}) match '[' exp => Number = 1 match ']' THEREFORE VAR = ({'foo','bar'})[1] THEREFORE prefixexp = VAR THEREFOER exp = VAR THEREFORE explist = VAR match ')' THEREFORE args = (VAR) => print(VAR) 
+5
source

Source: https://habr.com/ru/post/955825/


All Articles