让我们看看你的函数 count/2。
count([Head|Tail], Counter) ->
fun(Element) -> if
[Head|Tail] == [] -> Counter;
Element == Head -> count(Tail, Counter + 1);
Element /= Head -> count(Tail, Counter)
end
end.
此函数包含作为函数定义的语句。这是最后一条语句,它成为返回值。所以调用:
lists:map(count(L, 0), E).
确实返回了一个函数列表。查看 count 函数的定义,它确实对 count 进行了递归调用,并且如果它曾经被调用过,它实际上可能会起作用,但事实并非如此。
我们可以在程序末尾添加一条语句来调用 的所有元素,方法是这样更改调用:
numberOfOccurences(L, E) ->
[F(E) || F <- lists:map(count(L, 0), E)].
或者,如果您对 map 功能有偏好:
numberOfOccurences(L, E) ->
lists:map(fun(F) -> F(E) end, lists:map(count(L, 0), E)).
但是,这些不运行。
mymodule:numberOfOccurences([1,2,"abc",2,1,"abc",4,1,1], [1,2,3,"abc"])。**异常错误:函数mymodule中的错误函数4:'-numberOfOccurences/2-lc$^0/1-0-'/2(/home/tony/Projects/temp/src/mymodule.erl,第20行)
3>
作为风格问题,如果传递计数参数而不是以这种方式使用闭包,代码将更容易推理。有时闭包是必不可少的,例如在使用 spawn/1 时,但这不是其中一种情况。
分析问题我同意第一阶段是地图,但是我建议最好通过折叠来计算匹配元素。但是,我通常会用列表推导代替地图调用。我只是觉得它看起来更整洁。
所以这是我的解决方案:
-module occurances.
-export [count/2].
count(Data,KeyList) ->
[ lists:foldl(
fun(X,Count) when X =:= Key -> Count+1;
(_,Count) -> Count
end,
0,Data)
|| Key <- KeyList].
注意与 foldl 函数内的值 Key 匹配的模式将导致影子变量警告。X =:= Key 被使用。
发生次数:计数([1,2,"abc",2,1,"abc",4,1,1], [1,2,3,"abc"])。[4,2,0,2]
因此,在使代码实际工作之后,如何放入一个闭包以便例如可以调用 spawn/1 。让我们编辑我们的工作代码模块来制作这样一个闭包,并让闭包将结果写入标准 io 以便我们可以看到结果。
make_closure(Data,KeyList) ->
fun() ->
io:format("~p~n",[count(Data,KeyList)])
end.
8> F=occurances:make_closure([1,2,"abc",2,1,"abc",4,1,1], [1,2,3,"abc"]).
F=occurances:make_closure([1,2,"abc",2,1,"abc",4,1,1], [1,2,3,"abc"]).
#Fun<occurances.0.132489632>
9> spawn(F).
spawn(F).
[4,2,0,2]
<0.107.0>
10>