Erlang进程事件错误

时间:2013-02-09 21:20:03

标签: process erlang

我基本上都遵循本网站上的教程Learn you some Erlang:Designing a concurrent application,我尝试使用以下命令运行下面的代码并在第48行遇到错误。我确实关闭了我的防火墙以防万一问题,但没有运气。我在windows xp SP3上。

9基C(事件)。

{确定,事件}

10 -10 f()的

确定

11>事件:启动( “事件”,0)

=错误报告==== 2013年2月9日:: 15:05:07 === 过程中的错误< 0.61.0>退出值:{function_clause,[{event,time_to_go,[0],[{file,“event.erl”},{line,48}]},{event,init,3,[{file,“event。 ERL“},{线,31}]}]}

< 0.61.0>

12所取代;

-module(event).
-export([start/2, start_link/2, cancel/1]).
-export([init/3, loop/1]).
-record(state, {server,
                name="",
                to_go=0}).

%%% Public interface
start(EventName, DateTime) ->
    spawn(?MODULE, init, [self(), EventName, DateTime]).

start_link(EventName, DateTime) ->
    spawn_link(?MODULE, init, [self(), EventName, DateTime]).

cancel(Pid) ->
    %% Monitor in case the process is already dead
    Ref = erlang:monitor(process, Pid),
    Pid ! {self(), Ref, cancel},
    receive
        {Ref, ok} ->
            erlang:demonitor(Ref, [flush]),
            ok;
        {'DOWN', Ref, process, Pid, _Reason} ->
            ok
    end.

%%% Event's innards
init(Server, EventName, DateTime) ->
    loop(#state{server=Server,
                name=EventName,
                to_go=time_to_go(DateTime)}).

%% Loop uses a list for times in order to go around the ~49 days limit
%% on timeouts.
loop(S = #state{server=Server, to_go=[T|Next]}) ->
    receive
        {Server, Ref, cancel} ->
            Server ! {Ref, ok}
    after T*1000 ->
        if Next =:= [] ->
            Server ! {done, S#state.name};
           Next =/= [] ->
            loop(S#state{to_go=Next})
        end
    end.

%%% private functions
time_to_go(TimeOut={{_,_,_}, {_,_,_}}) ->
    Now = calendar:local_time(),
    ToGo = calendar:datetime_to_gregorian_seconds(TimeOut) -
           calendar:datetime_to_gregorian_seconds(Now),
    Secs = if ToGo > 0  -> ToGo;
              ToGo =< 0 -> 0
           end,
    normalize(Secs).

%% Because Erlang is limited to about 49 days (49*24*60*60*1000) in
%% milliseconds, the following function is used
normalize(N) ->
    Limit = 49*24*60*60,
    [N rem Limit | lists:duplicate(N div Limit, Limit)].

2 个答案:

答案 0 :(得分:3)

它在您的计算机上纯粹在本地运行,因此防火墙不会影响它。

问题是你在启动它时给出的第二个参数event:start("Event",0).

错误原因:

{function_clause,[{event,time_to_go,[0],[{file,"event.erl"},{line,48}]},{event,init,3,[{file,"event.erl"},{line,31}]}]}

表示它是function_clause错误,这意味着函数定义中没有与参数匹配的子句。它还告诉你,第48行的函数event:time_to_go/1失败,并且使用参数0调用它。

你看一下函数time_to_go/你会发现它希望它的参数是2个元素的元组,其中每个元素是3个元素的元组:

time_to_go(TimeOut={{_,_,_}, {_,_,_}}) ->

此参数的结构为{{Year,Month,Day},{Hour,Minute,Second}}。如果您向后关注此参数,则time_to_go/会从init/3调用time_to_go/1,其中DateTimeinit/3的参数是init/3的第3个参数。现在差不多了。现在start/2) and the 3rd argument to(和start_link / 2 is the second argument to init / 3 event:start("Event",0). start / 2`中产生的过程的函数。

因此,当您致电0时,此处的time_to_go/1会被传递到新进程中的调用event:start("Event", {{2013,3,24},{17,53,62}}).函数中。格式错了。你应该用{{1}}

之类的东西来调用它

答案 1 :(得分:1)

要为rvirding的答案添加背景,您会收到错误,因为  示例一直工作到最后的代码片段为止 我所知。首先使用normalize函数,它处理 问题。然后在问题中的示例后面的段落 上面,文字说:

  

它有效!对事件模块最不感兴趣的是我们   必须输入剩余的时间,以秒为单位。如果我们这样会好得多   可以使用标准格式,如Erlang的日期时间({{Year, Month, Day}, {Hour, Minute, Second}})。只需添加以下功能即可   将计算你当前时间之间的差异   电脑和你插入的延迟:

下一个代码片段引入了仅占用日期/时间的代码位 将其更改为最后一次。

我无法轻松链接到该文件的所有过渡版本 这就是为什么直接使用示例尝试链接文件不起作用的原因 在这种情况下超级容易。如果代码是一步一步,片段 通过片段,一切都应该工作正常。对不起,感到困惑。