2011-09-19 34 views
4

我正在嘗試使用fermats method創建素數分解器。不允許在Guard中使用函數。建議備用實施要

此行生成錯誤

find_factors(A, B, FactorThis) when is_a_square(B) == true -> 

調用本地/進口功能is_a_square/1是後衛非法

唯一可能替代我看到這個實現是使用某種該函數內的case語句。我避免了這一點,因爲它可能會搞砸尾遞歸。我是Erlang noob。 還有什麼其他的方式來實現這個功能?

get_int_part_of_sqrt(N) -> 
    trunc(math:sqrt(N)). 

is_a_square(N) -> 
    get_int_part_of_sqrt(N) * get_int_part_of_sqrt(N) == N. 

calculate_new_b(A, FactorThis) -> 
    NewB = trunc(abs((A * A) - FactorThis)), 
    io:format("Calculate_new_b A^2 ~w- FT ~w= NB ~w ~n",[A*A,FactorThis,NewB]), 

find_factors(A, B, FactorThis) when is_a_square(B) == true -> 
    io:format("find_factors true ~w ~w~n", [A, B]), 
    {ok, A + get_int_part_of_sqrt(B), A - get_int_part_of_sqrt(B)}; 

find_factors(A, B, FactorThis) -> 
    io:format("find_factors false ~w ~w~n", [A, B]), 
    NewA = A + 1, 
    NewB = calculate_new_b(NewA, FactorThis), 
    find_factors(NewA, NewB, FactorThis). 

Research1

Research2

編輯。 調用calculate_new_b中的固定參數

添加缺少get_int_part_of_sqrts。

回答

12

Erlang故意限制您允許在警衛中調用哪些功能。 Here's這是一個相當近期的論證,它的優點和缺點。

唯一的解決方法是使用case。你可以很容易地重寫這段代碼使用case

find_factors(A, B, FactorThis) -> 
    case is_a_square(B) of 
     true -> io:format("  find_factors true ~w ~w~n", [A, B]), 
       {ok, A + B, A - B}; 

     false-> io:format("  find_factors false ~w ~w~n", [A, B]), 
       NewA = A + 1, 
       NewB = calculate_new_b(NewA, FactorThis), 
       find_factors(NewA, NewB, FactorThis). 

注意上面的代碼仍然是正確的尾遞歸。

(我修改你的代碼稍微拿那我猜你的意思是不是有存在的部分)

+0

是的。這就是我想到的。我從有問題的代碼中刪除了垃圾。這是評論殘留,不正確地刪除。謝謝。 – EvilTeach

+0

不幸的是,許多允許用戶在警衛中定義功能的支持者錯過了這一觀點,或者提出了這樣的改變以使其「安全」,從而徹底改變了部分語言。 – rvirding

+0

我必須重新閱讀討論。我對Haskell背景的直覺是不同意的,並且建議應該有方法將一個函數標記爲無副作用(從Haskeller的角度來看,甚至一些批准的函數,比如'node/0'和'self/0'不是),但這看起來並不合適。 – Dan

2

這裏是另一種方式來重構解決此問題。

在呼叫者處添加所需的保護功能作爲參數。這將其從具有可能的副作用的功能轉變爲真或假,其沒有副作用。然後直接模式匹配將完成這項工作。

main() -> 
    List2 = find_factors_2 (10, 5, 105, is_a_square(5)), 
    io:format("method 2 ~w~n", [List2]). 

find_factors_2(A, B, _FactorThis, true) -> 
    Offset = get_int_part_of_sqrt(B), 
    {A + Offset, A - Offset}; 

find_factors_2(A, _B, FactorThis, false) -> 
    NewA = A + 1, 
    NewB = calculate_new_b(NewA, FactorThis), 
    find_factors_2(NewA, NewB, FactorThis, is_a_square(NewB)). 
+0

是的,那也行得通。這兩者確實相當,所以這是一個審美偏好的問題。我發現有趣的是,支持這種模式匹配的所有語言(據我所知)允許它在函數頭部和身體中。 – Dan

+0

我不同意。你的解決方案更好,因爲它不需要額外的參數。實際上,我正在向調用者公開一些內部信息。無論如何,這是另一種做法,可能對某個人有用。 – EvilTeach