开发者

Erlang: Recursion vs Lists

I'm newbie in Erlang and i'm trying to understand why recursion working faster than using list (that can even got an error "can't allocate memory in heap").

I created two functions to find primes for a value (pretty straight forward):

  1. using recursion:

    find_factor_rec(List, Max, _, NextValue)
        when NextValue > Max ->
            List;
    
    find_factor_rec(List, Max, Value, NextValue)->
        if (Value rem NextValue =:= 0) ->
            find_factor_rec([NextValue|List], Max, Value, NextValue + 1);
        true ->
            find_factor_rec(List, Max, Value, NextValue + 1)
        end
    .
    
    find_factors(Val)->开发者_开发问答;
        find_factor_rec([], round(math:sqrt(Val)) + 1, Val, 2).
    
  2. list

    find_factors1(Val) ->
        [X || X <- lists:seq(2, round(math:sqrt(Val)) + 1), Val rem X =:= 0].
    

while i'm passing small values - both are at the same time. When i'm passing huge values like 403851455234578 the second function became slower and slower and even throws error.

Could someone please explain why first function better than list? Are there better way to rewrite function? Are there any name convention for the first listing? (function plus their "child-recursive-functions")

Thanks.


The first function is faster because you only calculate the top number once. In the second function, you create all the numbers from 2 to the square root plus one. That's 20096056 integers in a list.

lists:seq(2, round(math:sqrt(Val)) % Creates a list from 2 to 20096056

Your problem doesn't suit itself to a solution that creates the whole search space in memory, because of space and performance reasons.

To conclude, the use of lists here is very sub-optimal.


As for naming conventions: when the function has a different arity (a different number of arguments) one usually names it the same. Erlang does not see it as the same function though, only functions with the same name and arity are considered equal.

find_factors(Val)-> find_factor_rec([], round(math:sqrt(Val)) + 1, Val, 2).

find_factors(List, Max, _, NextValue) when NextValue > Max ->
    List;
find_factors(List, Max, Value, NextValue) ->
    if 
        (Value rem NextValue =:= 0) ->
            find_factors([NextValue|List], Max, Value, NextValue + 1);
        true ->
            find_factors(List, Max, Value, NextValue + 1)
    end.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜