Erlang索引子句是如何处理的?

时间:2011-02-07 11:57:28

标签: indexing erlang clause

我来自Prolog背景。 Prolog通常对谓词的第一个参数进行索引(大多数体面的系统允许你改变它,对多个参数进行索引等)。无论如何,了解引擎索引子句如何允许您安排参数和谓词以获得更好的性能。

我最近在Erlang编写了一些代码,但是没有看到有关它如何索引子句头的任何信息,以及我应该如何安排参数和子句。有人知道吗?

感谢。

1 个答案:

答案 0 :(得分:12)

Erlang索引从左到右,任何深度和所有类型的所有参数。我们使用的基本算法在Simon Peyton Jones的The Implementation of Functional Programming Languages中描述,我修改它以适应Erlang处理类型的方式。即使现在有点老了,这本书也是一本好书,对我来说是一次真正的AHA体验。

这意味着没有必要重新排序参数以尝试优化模式匹配,至少不是速度。保持一致和清晰要好得多,这就是这样做的方式,Is there an idiomatic way to order function arguments in Erlang?。这意味着代码没有问题,如:

foo(X, [{a,A}|Rest], ...) -> ... ;
foo(X, [{b,B}|Rest], ...) -> ... ;
foo(X, [{c,C}|Rest], ...) -> ... ;
foo(X, [{d,D}|Rest], ...) -> ... ;
...

通过将其分解为嵌套的case表达式,从来没有必要尝试“帮助”编译器,它通常会更糟。这样做的唯一原因是如果它使代码更清晰地显示出你想要的东西。

如果您确实想尝试优化模式匹配,请尝试重新排序子句,以便将文字出现的所有情况捆绑在一起。例如:

foo(1, ...) -> ... ;
foo(2, ...) -> ... ;
foo(7, ...) -> ... ;
foo(8, ...) -> ... ;
foo(I, ...) when is_integer(I), I >= 3, I =< 6 ->
    ... .

优于

foo(1, ...) -> ... ;
foo(2, ...) -> ... ;
foo(I, ...) when is_integer(I), I >= 3, I =< 6 ->
    ... ;
foo(7, ...) -> ... ;
foo(8, ...) -> ... .

索引会更好,但同样不要过度,因为差异不是很大,请保持清晰。这在任何深度都有效,例如在第一个代码示例中,列表中包含元组的第一个元素。

这大部分都是功能语言的标准。