执行 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.
undef
错误意味着程序尝试调用未定义的函数。 发生这种情况的原因有以下三个:
- 没有具有该名称的模块(在本例中为
rand
(,或者由于某种原因无法找到并加载它
该 - 模块没有定义具有该名称和 arity 的函数。 在这种情况下,所讨论的函数
uniform
一个参数。 (请注意,在 Erlang 中,具有相同名称但不同参数数量的函数被视为单独的函数。 - 有这样的函数,但它没有导出。
您可以通过在 Erlang shell 中键入 l(rand).
来检查第一个,通过运行 rand:module_info(exports).
来检查第二个和第三个。
在这种情况下,我怀疑问题是您使用的是旧版本的 Erlang/OTP。 如文档中所述,rand
模块是在 18.0 版中引入的。
如果您提供用于未来问题的 Erlang/OTP 版本,那就太好了,因为 Erlang 多年来发生了很大变化。据我所知,至少在最近的 Erlang 版本中没有 arity 2 rand:uniform
,这就是您遇到undef
错误的原因,在这种情况下,您可以使用像 crypto:rand_uniform(Low, High).
这样的crypto:rand_uniform/2
希望这对:)有所帮助