这是一个Lua 5.2.2脚本,显示了表的声明和索引:
> mylist = {'foo', 'bar'}
> print(mylist[1])
foo
为什么以下声明不合法?
> print({'foo', 'bar'}[1])
stdin:1: ')' expected near '['
我想不出任何其他语言,其中文字不能替代参考(当然,除非需要左值)。
FWIW,将表格文字括起来使声明成为合法的:
> print(({'foo', 'bar'})[1])
foo
答案 0 :(得分:10)
这也与Lua这个语法有效的事实有关:
myfunc { 1, 2, 3 }
它相当于:
myfunc( { 1, 2, 3 } )
因此表达如下:
myfunc { 1, 2, 3 } [2]
被解析为:
myfunc( { 1, 2, 3 } )[2]
首先评估函数调用,然后进行索引。
如果{1,2,3}[2]
可以被解析为有效的索引操作,则可能导致前一个表达式中出现歧义,这需要更多的前瞻性。 Lua团队选择通过使其成为单通道编译器来快速制作Lua字节码编译器,因此它只使用最少的前瞻扫描源代码一次。 This message to lua mailing list from Roberto Ierusalimschy (lead Lua developer)指向那个方向。
字符串文字和方法调用存在同样的问题。这是无效的:
"my literal":sub(1)
但这是有效的:
("my literal"):sub(1)
再一次,Lua允许这样:
func "my literal"
等同于:
func( "my literal" )
答案 1 :(得分:5)
定义语法here,非括号版本无效但括号为的原因是因为语法树采用不同的路径并期望结束括号)
因为那里< em> 在该上下文中不应该是其他符号。
在第一种情况下:
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 ')'
另一方面用括号:
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)