类型检查 guard(例如,is_float/1
)在很多情况下都很有用,但是它们很冗长。我建议允许 is_
系列函数接受多个参数,这将在常见情况下显著减少源代码的体积。
其中 is_type
代表任何 is_
系列函数,例如 is_float
is_type(A, B, C, ...)
等价于 (is_type(A) andalso is_type(B) andalso is_type(C)...)
。
is_type
函数现在可以接受 1 到 N 个参数,其中 N 是函数元数的实现定义限制。
旧式的 guard(例如,float/1
)不会改变,因为其中一些兼具类型转换的功能。
在 erlang 模块中直接引用这些函数仅针对单参数版本(例如,fun erlang:is_float/1
)。
我发现添加类型检查 guard 不仅是为了安全,而且是为了提高代码生成质量,尤其是在使用浮点数时。用 Erlang 编写具有 is_float
guard 的三元素或四元素向量数学函数非常冗长。is_float
检查使得原本只需一行的函数,由于添加了多行 guard 而显得臃肿。
以下是 Wings3D 项目中的一个示例
cross({V10,V11,V12}, {V20,V21,V22})
when is_float(V10), is_float(V11), is_float(V12),
is_float(V20), is_float(V21), is_float(V22) ->
{V11*V22-V12*V21,V12*V20-V10*V22,V10*V21-V11*V20}.
is_float
检查显著提高了生成的代码质量,允许浮点数保存在虚拟机寄存器中,而不是分配在堆上。如果允许 is_float
接受多个参数,则可以将此代码重写为
cross({V10,V11,V12}, {V20,V21,V22})
when is_float(V10,V11,V12,V20,V21,V22) ->
{V11*V22-V12*V21,V12*V20-V10*V22,V10*V21-V11*V20}.
在第二个版本中,意图一目了然,并且添加类型检查的源代码级别开销不会使函数显得臃肿。
多年来,Erlang 系统越来越依赖于类型检查。有 dialyzer 和 typer 工具。编译器可以静态地推断类型并因此生成更好的代码。在源代码级别使类型检查 guard 更轻量级,鼓励了它们的使用,并且更符合该语言的整体语法密度。
如果实现此提案,所有使用 is_type/1
函数的地方仍然可以正常工作。直接引用 erlang:is_float
、erlang:is_atom
等作为 fun 的方式仍然可以按照最初的意图工作。
无。
本文档已置于公共领域。