fun M:F/A
中使用变量 #fun M:F/A
应该允许 M
、F
和/或 A
为变量。
目前,fun M:F/A
形式要求 M
为原子,F
为原子,A
为非负整数。 此规则被推广为允许它们中的任何一个或全部为变量。
现在不推荐使用元组 {M,F,A}
来表示函数。 然而,有时一些信息在运行时才可用。 例如,行为的作者可能希望引用回调模块中的 start/0
函数,但在运行时可能存在任意数量的回调模块。
形式为 M:F(E1, ..., En)
的调用中,模块名和函数名可以是原子或变量,而 fun M:F/A
中它们却不能是变量,这是荒谬的。
事实证明,fun M:F/A
目前是作为对 erlang:make_fun(M, F, A)
的调用实现的,因此已经具备了根据运行时数据创建此类 fun 的能力。 缺少的就是围绕它的一些语法包装。
这里填补的空白是在实践中感受到的。 请参阅 2008 年 9 月 Erlang 邮件列表中的一个帖子。 该提案推广了现有形式,但没有比现有函数调用语法已经推广的范围更大。
也许需要解释的是该提案的限制。
首先,扩展是从常量到常量或变量,而不是到任意表达式。 这主要是为了避免混淆解析器和人们。 可以通过编写 M = E1, F = E2, A = E3, fun M:F/A
来实现 fun (E1):(E2)/(E3)
的效果,因此不会损失表达能力。 由于 Erlang 的 lambda 形式等价物以“fun (
” 开头,因此 fun (E1):...
将难以解析,并且很容易让人感到困惑。
其次,该扩展仅适用于 fun M:F/A
,而不适用于 fun F/A
。 这是因为没有可调用的 erlang:make_fun/2
; fun F/A
的实现非常棘手,涉及到创建专用胶水函数。 对于许多目的来说,fun ?MODULE:F/A
将可以替代。
所有现有的 Erlang 代码在语义不变的情况下仍然可以接受。 没有添加新的函数或指令,因此使用新解析器生成的 BEAM 文件可以在较旧的版本中工作。
辅助文件 eep-0023-1.diff 是一个补丁文件,应用于 erl_parse.yrl。 经过 yecc 检查,该修补文件没有问题,并且生成的 .erl 文件可以干净地编译。 但是,这就是已经完成的全部测试。
该实现所做的全部操作就是
fun M:F/A
,其中 M
、F
和 A
是常量或变量,erlang:make_fun(M, F, A)
。 只涉及解析器。本文档已置于公共领域。