Function 为什么不';Lua表达式中的t匿名函数?
有人能解释一下为什么Lua中的匿名函数构造不是一个成熟的表达式吗?对我来说,这似乎是一个奇怪的现象:它(稍微)违背了函数应该是第一类对象的想法,并且(不经常但偶尔)在一种真正经过深思熟虑且优雅的语言中造成了不便 例如,使用命令行Lua和变通方法Function 为什么不';Lua表达式中的t匿名函数?,function,lua,expression,Function,Lua,Expression,有人能解释一下为什么Lua中的匿名函数构造不是一个成熟的表达式吗?对我来说,这似乎是一个奇怪的现象:它(稍微)违背了函数应该是第一类对象的想法,并且(不经常但偶尔)在一种真正经过深思熟虑且优雅的语言中造成了不便 例如,使用命令行Lua和变通方法 Lua 5.3.3 Copyright (C) 1994-2016 Lua.org, PUC-Rio > function(x) return x*x end (2) stdin:1: <name> expected near '('
Lua 5.3.3 Copyright (C) 1994-2016 Lua.org, PUC-Rio
> function(x) return x*x end (2)
stdin:1: <name> expected near '('
> square = function(x) return x*x end
> square(2)
4
Lua 5.3.3版权所有(C)1994-2016 Lua.org,临市局里约
>函数(x)返回x*x结束(2)
标准输入:1:预期接近'('
>平方=函数(x)返回x*x结束
>广场(2)
4.
哦,我明白了。对不起,需要圆括号
(function(x) return x*x end) (2)
我还是不明白为什么它设计成这样。简短回答
要调用函数,函数表达式必须是名称、索引值、另一个函数调用或括号内的表达式
长话短说
我不知道为什么它是这样设计的,但我确实查阅了,看看它到底是如何工作的。下面是函数调用的条目:
functioncall::=prefixexp参数| prefixexp':'名称参数
“args”只是括号中的参数列表。相关部分是“prefixexp”
前缀xp::=var | functioncall |'('exp')'
好的,我们可以调用另一个“functioncall”。“exp”只是一个普通表达式:
exp::=nil | false | true | numeric | LiteralString |'…'| functiondef | prefixexp | tableconstructor | exp binop exp | unop exp
所以我们可以调用任何表达式,只要它在括号内。“functiondef”包含匿名函数:
functiondef::=函数funcbody
funcbody::='('[parlist]')块结束
所以匿名函数是一个“exp”,而不是一个“prefixexp”,所以我们确实需要用括号括起来
什么是“var”
变量::=Name | prefixexp'['exp'].| prefixexp'.'Name
“var”是一个名称或一个索引值(通常是一个表)。请注意,索引值必须是一个“prefixexp”,这意味着在我们可以索引它们之前,字符串文本或表构造函数必须在括号中
总而言之:被调用的函数必须是名称、索引值、函数调用或括号内的其他表达式
最大的问题是:为什么“prefixexp”与“exp”的处理方式不同?我不知道。我怀疑这与保持函数调用和索引超出正常范围有关,但我不知道为什么这是必要的。Lua的函数调用语法中内置了一些语法糖。可以通过以下三种方式调用函数:
- 带括号的值列表
- 表构造函数(函数将表作为单个参数)
- 字符串文字
local value = function(args)
--does some stuff
end "I'm a literal" .. foo
如果我们允许像任何其他函数调用一样调用任意的、未解析的表达式,那么这意味着创建一个函数,使用字符串文本调用它,将该函数调用的结果与foo
连接,并将其存储在值中
但是…我们真的希望它起作用吗?也就是说,我们希望人们能够编写它并使其成为有效的Lua代码吗
如果这样的代码被认为难看或令人困惑,那么有几个选择
Lua不能使用字符串文本进行函数调用。毕竟,您只保存了2个括号。甚至可能不允许使用表构造函数,尽管这些构造函数不那么难看,也不太容易混淆。让每个人在所有函数调用中都使用括号
Lua可以这样做,只有在lambda的情况下,才可以防止使用字符串文本的函数调用。这需要对语法进行大量的去规范化
如果调用函数显然不是前面文本的预期结果,Lua可能会强制您在任何构造中插入括号
现在,有人可能会说,table\u name[var\u name]“literal”
对于正在发生的事情已经相当混乱了。但是,要防止这种情况发生,特别需要对语法进行去规范化。您必须添加所有这些特殊情况,例如name“literal”
是函数调用,而name.name>是函数调用“literal”
不是。因此选项2不适用
使用字符串文本调用函数的能力并不局限于Lua,但您必须使用特定的文本语法来获得它。此外,能够键入要求“module_name”
感觉是个好主意。由于这种调用被认为是一种重要的语法糖分,并得到了多种语言的支持,因此选项1不适用
所以你唯一的选择是#3:让人们把他们想调用的表达式括起来。Lua的设计并没有考虑到IIFEs。你也需要在Javascript中使用括号,因为在Javascript中使用括号的频率更高。在Lua中,Javascript中IIFEs的大部分内容将改为do…end
块。@Jasmijn:IIFEs可以重新绑定…
。使用{…}
“它(稍微)违背了函数应该是第一类对象的想法”不,它不是。第一类对象的性质和语法表达式的性质彼此无关。实际上(我知道这将把这一论点推向了极限,不必太认真)我可以想象一种新的blogop类型的语言完全是第一类的,但是没有任何语法来构造它。如果你有一个包含blobop的变量,那么你可以对它做任何你想做的事情,包括赋值。但是它是无用的。IMHO,作为第一类对象是有用的(在精神上,如果不是在法律条文中)您需要支持语法。