不允许使用 Guard 中的函数。需要替代实施的建议

发布于 2024-12-05 06:30:41 字数 1432 浏览 1 评论 0原文

我正在尝试使用 fermats 方法 创建素数分解器。

此行生成错误

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

对本地/导入函数 is_a_square/1 的调用在防护中是非法的

我看到此实现的唯一可能的替代方案是在函数中使用某种 case 语句。我正在避免这样做,因为它可能会搞砸尾递归。我是一个 Erlang 菜鸟。 还有哪些其他方法可以实现此功能?

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。

I am attempting to create a prime number factorizer, using fermats method.

This line generates an error

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

call to local/imported function is_a_square/1 is illegal in guard

The only possible alternative I see to this implementation is to use some sort of case statement within the function. I was avoiding that, as it might screw up the tail recursion. I am a Erlang noob. What other ways are there to implement this functionality?

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

Edited.
fixed argument in call to calculate_new_b

added missing get_int_part_of_sqrts.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

九八野马 2024-12-12 06:30:41

Erlang 故意限制你可以调用守卫的函数。 这是最近关于这样做的理由及其优点的讨论和缺点。

解决这个问题的唯一方法是使用 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).

请注意,上面的代码仍然是正确的尾递归。

(我对你的代码进行了一些修改,以删除我猜你不应该存在的部分)

Erlang deliberately restricts which functions you're allowed to call in guards. Here's a fairly recent discussion of the justification for this, its merits and drawbacks.

The only way around it is to use case. You can pretty easily rewrite this code to use 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).

Note that the above code is still properly tail-recursive.

(I modified your code a little to take out the parts that I'm guessing you meant not to have there)

微凉徒眸意 2024-12-12 06:30:41

这是围绕该问题进行重构的另一种方法。

添加所需的保护函数作为调用者的参数。这将其从可能有副作用的函数变为没有副作用的 true 或 false。然后直接模式匹配就可以完成这项工作。

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

Here is another way to refactor around the issue.

Add the desired guard function as an argument at the caller. This turns it from a function with possible side effects, into true or false, which have no side effects. Then straight pattern matching will do the job.

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)).
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文