Erlang中的排列示例

时间:2015-12-09 12:50:52

标签: erlang

我对Erlang Perms的实现有疑问:

 perms([]) -> [[]];
 perms(L) -> [[H|T] || H <- L, T <- perms(L--[H])].

上面的代码来自一本名为 Erlang Programming 的书,它看起来非常简单但运行完美。我困惑的是它是如何工作的。例如,让我们使用类似perms("12")的参数运行它,然后我们分析递归过程。我认为第一个返回的结果将类似[[1|perms[2]->[[2]|[[]]]],这等于[[1|[[2]|[[]]]]。但它在Erlang shell中是一个错误的表达。

1 个答案:

答案 0 :(得分:10)

列表推导的一般行为是生成所有生成器的叉积(在应用定义的过滤器之后)。通过一个例子可以更好地说明:

1> [{X,Y} || X <- [1,2,3], Y <- [a,b,c]].
[{1,a},{1,b},{1,c},{2,a},{2,b},{2,c},{3,a},{3,b},{3,c}]
2> 
在排列代码示例中,列表推导以这种方式执行:

H <- L是一个生成器,它会为输入列表L的每个项生成一个值。在您的情况下,L =&#34; 12&#34;,它将生成2个字符的字符{{ 1}}和$1,它将使用第二个生成器的结果构建叉积:$2

这里有一些非常聪明的东西,第二个发生器依赖于第一个,第一个发生器的每个元素将与来自第二个发生器的自己的列表组合。因此,T <- perms(L--[H])将与$1 = perms(L--[$1])

中生成的字词组合使用

如果您尝试评估perms("2"),则相同的分析会显示第一个生成器会生成一个与perms("2")结合的单个术语$2

最后一项评估为perms([])并生成一个空列表。

我们现在可以构建中间结果:[[]]

此结果将生成单个术语[[H|T]] = [[$2|[]]] = [[$2]]。因此,最高级别的结果将是(考虑所有生成的术语)[$2]