Lua中自调用匿名函数出现错误

3

我想在Lua中使用自执行匿名函数,但是遇到了一些奇怪的行为。

下面这段代码:

(function ()
  print("self-invoking approach")
end)()

print("standard approach")

正常工作,并打印以下输出:

self-invoking approach
standard approach

但是将两者颠倒:

print("standard approach")

(function ()
  print("self-invoking approach")
end)()

会导致此错误:

  hammerspoon   lua temp.lua
standard approach
lua: temp.lua:1: attempt to call a nil value
stack traceback:
    temp.lua:1: in main chunk
    [C]: in ?

奇怪的是,当在Lua REPL中运行代码时,只有在函数形式为第二个参数且两个调用都被包装在一个外部调用的函数中时才会出现故障:

function foo()
    print("standard approach")

    (function ()
      print("self-invoking approach")
    end)()
end

foo()

这里发生了什么?

1个回答

7
这是一种语法歧义。无法工作的情况被解析为:
print("standard approach")(function ()
  print("self-invoking approach")
end)()

换句话说,它是在打印“标准方法”后,取该打印语句的返回值(即“nil”),并试图将其作为自调用函数的参数进行调用(如果没有崩溃,在这之后还会尝试调用结果)。要修复它,在第一个print函数调用的末尾添加分号。

1
这不是歧义。解析器会取最长的有效表达式。 - lhf
@lhf是吗?我认为这是一种歧义,并且选择最长的有效表达式来解决歧义。 - Joseph Sible-Reinstate Monica
此外,在Lua 5.1中,它确实无法解析,并显示错误消息“模糊的语法(函数调用x新语句)”。 - Joseph Sible-Reinstate Monica
哇!我很惊讶。其他语言是否也有这种行为?我以前从未见过。我决定将“;”直接放在函数定义之前(;(function...)),以确保它永远不会被视为先前语句的一部分。 - Keith Bennett
2
在JavaScript中尝试一下这个:console.log("test") ( () => console.log("foo"))() 同样的问题,同样的解决方案(添加一个;)。这是因为括号在许多编程语言中用于多个不同的目的,可能会导致这些歧义。 - DarkWiiPlayer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接