为什么表格文字与Lua中的表格引用区别对待?

Ell*_*tus 6 lua lua-table

这是一个Lua 5.2.2脚本,显示了表的声明和索引:

> mylist = {'foo', 'bar'}
> print(mylist[1])
foo
Run Code Online (Sandbox Code Playgroud)

以下声明为何不合法?

> print({'foo', 'bar'}[1])
stdin:1: ')' expected near '['
Run Code Online (Sandbox Code Playgroud)

我想不出任何其他语言,其中文字不能替代参考(当然,除非需要左值).

FWIW,使表格文字具有括号,使声明合法:

> print(({'foo', 'bar'})[1])
foo
Run Code Online (Sandbox Code Playgroud)

Lor*_*ica 10

这也与Lua这个语法有效的事实有关:

myfunc { 1, 2, 3 }
Run Code Online (Sandbox Code Playgroud)

它相当于:

myfunc( { 1, 2, 3 } )
Run Code Online (Sandbox Code Playgroud)

因此表达式如:

myfunc { 1, 2, 3 } [2]
Run Code Online (Sandbox Code Playgroud)

被解析为:

myfunc( { 1, 2, 3 } )[2]
Run Code Online (Sandbox Code Playgroud)

所以首先评估函数调用,然后进行索引.

如果{1,2,3}[2]可以将其解析为有效的索引操作,则可能导致前一个表达式中出现歧义,这需要更多的前瞻性.Lua团队选择通过使其成为单通道编译器来快速制作Lua字节码编译器,因此它只使用最少的前瞻扫描源代码一次.来自Roberto Ierusalimschy(Lua开发人员)的lua邮件列表的这条消息指向了这个方向.

字符串文字和方法调用存在同样的问题.这是无效的:

"my literal":sub(1)
Run Code Online (Sandbox Code Playgroud)

但这是有效的:

("my literal"):sub(1)
Run Code Online (Sandbox Code Playgroud)

再一次,Lua允许这样:

func "my literal"
Run Code Online (Sandbox Code Playgroud)

等同于此:

func( "my literal" )
Run Code Online (Sandbox Code Playgroud)


Hen*_*nyH 5

继续这里定义的语法,非括号版本无效但括号为的原因是因为语法树采用不同的路径并且期望一个右括号,)因为在该上下文中不应该有其他符号.

在第一种情况下:

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 ')'
Run Code Online (Sandbox Code Playgroud)

另一方面,括号:

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)
Run Code Online (Sandbox Code Playgroud)

  • @espertus我不确定为什么他们决定这样做,你可能是正确的预先捕获错误.我实际上遇到过这个**确切的**问题之前和想过(来自很多python之后)*什么?为什么不认为工作*. (2认同)