无法在 Erlang 中生成进程

Can't spawn process in Erlang

我不太清楚为什么我无法得到这个,但我确信答案非常简单。我只是在测试一些东西,在我的测试中发现我想在我的 gen_server.

handle_info 内生成一个进程

然而,尽管我尝试了不同的组合,但我从我的 child 中获得的最佳结果是死于错误并返回 {undef, [{bob, hello, [], []}]}

代码:

-module(test).
-behaviour(gen_server).
-export([start_link/1, init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

start_link(Args) ->
    gen_server:start_link({local, Args}, ?MODULE, Args, []).

init(Args) ->
    io:format("Init ~p ~p~n",[self(), Args]),
    {ok, Args}.

handle_call(_, _, State) ->
    io:format("Call ~p~n",[self()]),
    {reply, ok, State}.

handle_cast(_, State) ->
    io:format("Cast ~p~n",[self()]),
    {noreply, State}.

handle_info(_, State) ->
    io:format("Info ~p~n",[self()]),
    spawn(?MODULE,fun hello/1,[]),
    {noreply, State}.

terminate(_, _) ->
    ok.

code_change(_, State, _) ->
    {ok, State}.

hello([]) ->
    io:format("WOOT ~p~n",[self()]).

我的第一个目标是确定是否可以使用一个模块启动多个服务器。第二个是如果 handle_info 是在一个单独的进程中执行的……出于某种原因,当我读到它是异步的时,我认为它是在另一个进程中。现在第三个是在该调用中生成一个进程。

我的典型 shell 是这样的(带有注释):

> c(test), {ok, P} = gen_server:start_link(bob)
> %% Warns me the function hello in any incarnation is not used
> P ! woot.
> %% An error of some kind depending on what I've done
> f(P), gen_server:stop(bob).

我将 hello/1[]_hello/0 一起使用。以及 spawn/1spawn/3spawn_link/1spawn_link/3...我用过 ?MODULEtestState并将 chuckles {local, State} 作为模块参数。我已经放弃了我在多个网站上看到的内容,并在传递函数时输入 fun hello/0fun hello/1 。这会产生崩溃但消除了编译器警告。

我哪里错了?

spawn/3 的第三个参数是一个列表,其中包含衍生函数所需的参数数量。例如,如果派生函数接受 1 个参数,则列表将包含 1 个参数;如果生成的函数有 3 个参数,则列表将包含 3 个参数。最后,如果生成的函数接受 0 个参数,则列表将包含 0 个参数,即空列表。

您这样定义 hello

hello([]) ->
    io:format("WOOT ~p~n",[self()]).

这是一个参数为 1 的函数,不仅如此,与该函数匹配的唯一参数是空列表。为了将一个参数传递给您生成的函数,您必须编写:

spawn(?MODULE, hello ,[SomeArg])

并且,因为您要匹配一个将空列表作为唯一参数的函数,所以 SomeArg 必须是空列表:

spawn(?MODULE, hello, [[]])

注意 spawn/3 的语法是 MFA,即模块名称、函数名称、参数,这是一个包含参数的列表。

接下来,你还有两个问题:

  1. 你不应该像这里那样调用 gen_server:start_link(bob):

    {ok, P} = gen_server:start_link(bob)
    

    没有gen_server:start_link/1这样的函数。相反,您需要调用用户界面函数 start_link/1,然后它会调用 gen_server:start_link/3。您可能想要重命名您的用户界面函数 my_gen_server_starter(),以便您清楚它的作用。

  2. %% Warns me the function hello in any incarnation is not used

    您必须导出函数才能生成它。因为您没有导出该函数,并且因为模块内没有函数调用该函数,这意味着该函数永远无法执行。