作者
Richard A. O'Keefe <ok(at)cs(dot)otago(dot)ac(dot)nz>
状态
最终/R12B-4 已在 OTP 版本 R12B-4 中实现
类型
标准跟踪
创建于
2008-08-08
Erlang 版本
OTP_R12B-4

EEP 23: 允许在 fun M:F/A 中使用变量 #

摘要 #

fun M:F/A 应该允许 MF 和/或 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/2fun F/A 的实现非常棘手,涉及到创建专用胶水函数。 对于许多目的来说,fun ?MODULE:F/A 将可以替代。

向后兼容性 #

所有现有的 Erlang 代码在语义不变的情况下仍然可以接受。 没有添加新的函数或指令,因此使用新解析器生成的 BEAM 文件可以在较旧的版本中工作。

参考实现 #

辅助文件 eep-0023-1.diff 是一个补丁文件,应用于 erl_parse.yrl。 经过 yecc 检查,该修补文件没有问题,并且生成的 .erl 文件可以干净地编译。 但是,这就是已经完成的全部测试。

该实现所做的全部操作就是

  1. 接受 fun M:F/A,其中 MFA 是常量或变量,
  2. 当它们都是常量时,生成与过去相同的抽象语法项,
  3. 当至少有一个是变量时,假装已经编写了 erlang:make_fun(M, F, A)。 只涉及解析器。

版权 #

本文档已置于公共领域。