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

标签 erlang

我正在尝试使用fermats method创建一个素数分解器。 .

该行生成错误

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

Research1

Research2

已编辑。 修复了调用calculate_new_b时的参数

添加了缺少的 get_int_part_of_sqrts。

最佳答案

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

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

(我稍微修改了你的代码,删除了我猜你不应该有的部分)

关于erlang - 不允许使用 Guard 中的函数。需要替代实现的建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7474894/

相关文章:

erlang - “rebargenerate”在生成的版本中不包含一些依赖项

database - Ejabberd 的名册管理

erlang - 使用 Erlang 将十进制转换为十六进制?

erlang - erlang中的erl终端如何完整显示

Erlang:两阶段初始化安全吗?

Erlang Web 和 Inets BindAddress

tcp - Erlang TCP 服务器处理

java - jInterface 创建外部 Erlang 术语

erlang - 在 Erlang 中,record_info 和 tuple_to_list 返回相同的键顺序吗?

function - 在Erlang中,有没有一种创建空函数的方法?