我对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中是一个错误的表达。
答案 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]
。