我有两个清单:L和E。我试着写一个函数,它返回另一个列表,其中包含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).
mymodule:numberOfOccurences[1,2,"abc",2,1,"abc",4,1,1], [1,2,3,"abc"])
应该返回[4,2,0,2]
。但它返回了一个包含4个函数的列表。我做错了什么?
3条答案
按热度按时间jexiocij1#
What's happening here, is, if we unroll this map,
count(L, 0)
is being called first, then that resultant fun is being passed tolists:map
. When that resultant fun is being mapped with each member ofE
, and being passed to the anonymous function, the return value for most of the elements is the result of callingcount(Tail,Counter)
, which returns a function.Here's a rewritten version of your functions that works. The big thing is
count()
, and more importantly,count()
, so I'm storing the result ofcount()
calls intoF
, then calling that function with the passed element.So here is the updated module:
Results:
brvekthn2#
Let us look at your function count/2.
This function contains statement that is the definition of a function. This being the last statement it becomes the return value. So the call:
indeed returns a list of functions. Looking at the definition of the count function, it indeed makes recursive calls to count and might actually work if it was ever called, which it isn't.
We could add one statement to the end of your program to call all the elements of the by changing the call in this way:
Or alternatively, if you have a preference for the map function:
However these do not run.
mymodule:numberOfOccurences([1,2,"abc",2,1,"abc",4,1,1], [1,2,3,"abc"]). ** exception error: bad function 4 in function mymodule:'-numberOfOccurences/2-lc$^0/1-0-'/2 (/home/tony/Projects/temp/src/mymodule.erl, line 20)
3>
As a matter of style the code would be easier to reason about if count parameters were passed rather than using closures in this way. Sometimes closures are essential such as when using spawn/1, but this is not one of those cases.
Analysing the problem I agree the first stage is a map, however I suggest counting matching elements is best achieved with a fold. However I will generally substitute a list comprehension for a map call. I just think it looks tidier.
So here is my solution:
Note pattern matching with the value Key inside the foldl function will result in a shadow variable warning. X =:= Key is used instead.
occurances:count([1,2,"abc",2,1,"abc",4,1,1], [1,2,3,"abc"]). [4,2,0,2]
So having made the code actually work how about putting into a closure so that spawn/1 could be called for example. Let us edit our working code module to make such a closure, and let the closure write the result to standard io so we can see the result.
fjaof16o3#
For the record, you don't need a closure to define
count
.In my book, it's much clearer to have an explicit
count
function, and plug it appropriately.Edit: I've put list parameter second, to match
lists
module API.