【问题标题】:What causes Erlang runtime error {undef,[{rand,uniform,[2],[]},...]}?是什么导致 Erlang 运行时错误 {undef,[{rand,uniform,[2],[]},...]}?
【发布时间】:2019-08-19 20:09:00
【问题描述】:

在执行 Tarry 分布式算法的实现时,出现了一个我不知道如何解决的问题:包含错误 {undef,[{rand,uniform,[2],[]} 的崩溃。我的模块如下:

-module(assign2_ex).
-compile(export_all).

%% Tarry's Algorithm with depth-first version
start() ->
    Out = get_lines([]),
    Nodes = createNodes(tl(Out)),
    Initial = lists:keyfind(hd(Out), 1, Nodes),
    InitialPid = element(2, Initial),
    InitialPid ! {{"main", self()}, []},
    receive
        {_, List} ->
            Names = lists:map(fun(X) -> element(1, X) end, List),
            String = lists:join(" ", lists:reverse(Names)),
            io:format("~s~n", [String])
    end.

get_lines(Lines) ->
    case io:get_line("") of
        %% End of file, reverse the input for correct order
        eof -> lists:reverse(Lines);
        Line ->
            %% Split each line on spaces and new lines
            Nodes = string:tokens(Line, " \n"),
            %% Check next line and add nodes to the result
            get_lines([Nodes | Lines])
    end.

%% Create Nodes
createNodes(List) ->
    NodeNames = [[lists:nth(1, Node)] || Node <- List],
    Neighbours = [tl(SubList) || SubList <- List],
    Pids = [spawn(assign2_ex, midFunction, [Name]) || Name <-NodeNames],                         
    NodeIDs = lists:zip(NodeNames, Pids),
    NeighbourIDs = [getNeighbours(N, NodeIDs) || N <- lists:zip(NodeIDs,   Neighbours)],
    [Pid ! NeighbourPids || {{_, Pid}, NeighbourPids} <- NeighbourIDs],
    NodeIDs.

getNeighbours({{Name, PID}, NeighboursForOne}, NodeIDs) ->
    FuncMap = fun(Node) -> lists:keyfind([Node], 1, NodeIDs) end,
    {{Name, PID}, lists:map(FuncMap, NeighboursForOne)}.

midFunction(Node) ->
    receive
        Neighbours -> tarry_depth(Node, Neighbours, [])
    end.

%% Tarry's Algorithm with depth-first version
%% Doesn't visit the nodes which have been visited
tarry_depth(Name, Neighbours, OldParent) ->
    receive
        {Sender, Visited} ->
            Parent = case OldParent of [] -> [Sender]; _ -> OldParent end,
            Unvisited = lists:subtract(Neighbours, Visited),
            Next = case Unvisited of
                       [] -> hd(Parent);
                       _ -> lists:nth(rand:uniform(length(Unvisited)), Unvisited)
                   end,
            Self = {Name, self()},
            element(2, Next) ! {Self, [Self | Visited]},
            tarry_depth(Name, Neighbours, Parent)
    end.

【问题讨论】:

  • 您使用的是什么版本的 Erlang/OTP?您应该始终在问题中包含此类信息。请注意,rand module 仅存在于 18.0 或更高版本中。

标签: erlang


【解决方案1】:

undef 错误意味着程序试图调用未定义的函数。发生这种情况的原因有以下三个:

  • 没有具有该名称的模块(在本例中为 rand),或者由于某种原因无法找到并加载它
  • 模块未定义具有该名称和数量的函数。在这种情况下,有问题的函数是uniform,带有一个参数。 (请注意,在 Erlang 中,名称相同但参数数量不同的函数被视为单独的函数。)
  • 有这样的功能,但是没有导出。

您可以通过在 Erlang shell 中键入 l(rand). 来检查第一个,运行 rand:module_info(exports). 来检查第二个和第三个。

在这种情况下,我怀疑问题在于您使用的是旧版本的 Erlang/OTP。如the documentation 中所述,rand 模块是在 18.0 版中引入的。

【讨论】:

    【解决方案2】:

    如果您提供用于未来问题的 Erlang/OTP 版本会很好,因为 Erlang 多年来发生了很大变化。据我所知,至少在最近的 Erlang 版本中没有带有 arity 2 的 rand:uniform,这就是您得到 undef 错误的原因,在这种情况下,您可以使用 crypto:rand_uniform/2,例如 crypto:rand_uniform(Low, High). 希望这会有所帮助: )

    【讨论】:

      猜你喜欢
      • 2018-08-26
      • 2016-11-25
      • 1970-01-01
      • 1970-01-01
      • 2021-07-02
      • 2010-09-21
      • 2016-11-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多