我正在尝试使用动态创建的原子名称注册几个进程,如下所示:
keep_alive(Name, Fun) ->
register(Name, Pid = spawn(Fun)),
on_exit(Pid, fun(_Why) -> keep_alive(Name, Fun) end).
monitor_some_processes(N) ->
%% create N processes that restart automatically when killed
for(1, N, fun(I) ->
Mesg = io_lib:format("I'm process ~p~n", [I]),
Name = list_to_atom(io_lib:format("zombie~p", [I])),
keep_alive(Name, fun() -> zombie(Mesg) end)
end).
for(N, N, Fun) -> [Fun(N)];
for(I, N, Fun) -> [Fun(I)|for(I+1, N, Fun)].
zombie(Mesg) ->
io:format(Mesg),
timer:sleep(3000),
zombie(Mesg).
但list_to_atom/1
调用导致错误:
43> list_to_atom(io_lib:format("zombie~p", [1])).
** exception error: bad argument
in function list_to_atom/1
called as list_to_atom([122,111,109,98,105,101,"1"])
我做错了什么? 还有,有更好的方法吗?
答案 0 :(得分:5)
<强> TL; DR 强>
你不应该动态生成原子。从您的代码片段中可以看出,您可能正在尝试找到一些方法来灵活地命名进程,但原子不是它。使用某种类型的K / V商店而不是register/2
。
<强>讨论强>
原子是限制性的原因。它们应该代表程序的永恒结构,而不是当前的状态。原子是如此限制,以至于我想象你真正希望能够做的是使用任意Erlang值注册一个进程,而不仅仅是原子,并更自由地引用它们。
如果是这种情况,请选择以下四种方法之一:
#{Name => Pid}
的键/值对。答案 1 :(得分:2)
io_lib:format
返回潜在的“深层列表”(即它可能包含其他列表),而list_to_atom
则需要“平面列表”。您可以在io_lib:format
:
lists:flatten
来电
list_to_atom(lists:flatten(io_lib:format("zombie~p", [1]))).