如何在Erlang中使用闭包?

cie*_*bor 5 erlang closures functional-programming list anonymous-function

我有两个列表:L和E.我尝试编写一个函数,它返回另一个列表,其中包含L中元素的出现次数.

-module(mymodule).
-export([count/2]).
-export([numberOfOccurences/2]).

count([Head|Tail], Counter) ->
  fun(Element) -> if
    [Head|Tail] == [] -> Counter;
    Element == Head -> count(Tail, Counter + 1);
    Element /= Head -> count(Tail, Counter)
  end
end.

numberOfOccurences(L, E) -> 
    lists:map(count(L, 0), E).
Run Code Online (Sandbox Code Playgroud)

mymodule:numberOfOccurences[1,2,"abc",2,1,"abc",4,1,1], [1,2,3,"abc"])应该回来[4,2,0,2].但它返回一个包含4个函数的列表.我究竟做错了什么?

cho*_*ops 10

这里发生的事情是,如果我们count(L, 0)首先调用这个地图,那么首先会调用这个结果,然后传递给乐趣lists:map.当结果乐趣与每个成员映射E并传递给匿名函数时,大多数元素的返回值是调用的结果count(Tail,Counter),它返回一个函数.

这是你的功能的重写版本.最重要的是

  1. 我修复了基本情况,否则,当传递空集时,你可能会遇到匹配错误count(),更重要的是,
  2. 在你的闭包中,为了确保正确的递归,你需要调用返回值count(),所以我将count()调用的结果存储到F,然后用传递的元素调用该函数.

所以这是更新的模块:

-module(mymodule).
-export([count/2]).
-export([numberOfOccurences/2]).

count([],Counter) ->
    fun(_) -> Counter end;
count([Head|Tail], Counter) ->
    fun(Element) ->
        if
            Element == Head ->
                F = count(Tail, Counter + 1),
                F(Element);
            Element /= Head ->
                F = count(Tail, Counter),
                F(Element)
        end
    end.

numberOfOccurences(L, E) ->
        lists:map(count(L, 0), E).
Run Code Online (Sandbox Code Playgroud)

结果:

> mymodule:numberOfOccurences([1,2,"abc",2,1,"abc",4,1,1], [1,2,3,"abc"]).
[4,2,0,2]
Run Code Online (Sandbox Code Playgroud)