Использование функции в Guard запрещено. Требуются альтернативные варианты реализации - PullRequest
6 голосов
/ 19 сентября 2011

Я пытаюсь создать разложение простых чисел, используя метод fermats .

Эта строка выдает ошибку

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

вызов локальной / импортированной функции is_a_square / 1 недопустим в охране

Единственная возможная альтернатива, которую я вижу этой реализации, состоит в том, чтобы использовать какой-либо оператор case в функции. Я избегал этого, поскольку это могло бы испортить хвостовую рекурсию. Я эрланг нуб. Какие есть еще способы реализовать эту функцию?

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).

Исследования1

Исследования2

Под ред. исправлен аргумент в вызове Calculate_New_b

добавлено пропущенное get_int_part_of_sqrts.

Ответы [ 2 ]

13 голосов
/ 19 сентября 2011

Эрланг преднамеренно ограничивает, какие функции вы можете вызывать у охранников. Вот довольно недавнее обсуждение обоснования этого, его достоинств и недостатков.

Единственный способ обойти это - использовать 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).

Обратите внимание, что приведенный выше код по-прежнему правильно рекурсивно.

(я немного изменил ваш код, чтобы убрать те части, которые, как мне кажется, у вас не было)

2 голосов
/ 21 сентября 2011

Вот еще один способ реорганизации проблемы.

Добавить требуемую функцию защиты в качестве аргумента вызывающей стороне. Это превращает его из функции с возможными побочными эффектами в истинные или ложные, которые не имеют побочных эффектов. Тогда прямое сопоставление с образцом сделает всю работу.

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)).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...