我基本上都遵循本网站上的教程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)].
答案 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
,其中DateTime
,init/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}}
)。只需添加以下功能即可 将计算你当前时间之间的差异 电脑和你插入的延迟:
下一个代码片段引入了仅占用日期/时间的代码位 将其更改为最后一次。
我无法轻松链接到该文件的所有过渡版本 这就是为什么直接使用示例尝试链接文件不起作用的原因 在这种情况下超级容易。如果代码是一步一步,片段 通过片段,一切都应该工作正常。对不起,感到困惑。