2013-02-09 72 views
1

我基本上遵循本網站上的教程Learn you some Erlang:Designing a concurrent application,我試圖用下列命令運行下面的代碼,並在第48行出現錯誤。我確實關閉了防火牆,以防萬一問題,但沒有運氣。我在Windows XP SP3上。Erlang進程事件錯誤

9> c(事件)。

{ok,event}

10> f()。

ok

11> event:start(「Event」,0)。

=錯誤報告==== 9-FEB-2013 :: 15:05:07 === 錯誤在過程< 0.61.0>與出口值:{function_clause,[{事件,time_to_go,[0 ],[{file,「event.erl」},{line,48}]},{event,init,3,[{file,「event.erl」},{line,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)]. 

回答

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}} 。如果你按照這個論點倒退,你從init/3調用time_to_go/,其中time_to_go/1,DateTime的參數是init/3的第三個參數。現在幾乎在那裏。現在init/3是該進程中start/2催生了功能(和START_LINK/2 ) and the 3rd argument to的init/3 is the second argument to啓動/ 2`。

所以,當你調用event:start("Event",0).這是這裏的0被傳遞到通話time_to_go/1功能的新peocess,而且格式是錯誤的。你應該像event:start("Event", {{2013,3,24},{17,53,62}}).

+0

這是我的想法(我通過的論點是錯誤的),但我盲目地遵循網站上的教程,如果你看,你會發現他沒有得到任何錯誤運行它?感謝它現在的作品! – pandoragami 2013-02-10 06:54:00

+0

@lost_with_coding我檢查了這本書,對我來說,看起來'0'的調用是第一個版本,其中時間是秒(?)。據我所知,他沒有舉出第二版日期/時間元組的例子。他應該有的。如果我正確閱讀它。 – rvirding 2013-02-12 01:30:16

1

要添加背景rvirding的答案被調用它,你的錯誤,因爲 示例工作,直到最後的代碼段就 我所知。首先使用normalize函數,該函數處理 問題。然後在上面的問題 的示例之後的段落,文字說:

它的工作原理!事件模塊最後一件煩人的事情是我們 必須輸入剩下的秒數。如果我們 可以使用標準格式,比如Erlang的日期時間({{Year, Month, Day}, {Hour, Minute, Second}}),那將會好很多。只需添加下面的函數, 將計算當前時間之間的區別您 計算機上插入的延遲:

下一個片段介紹了碼位的是隻需要一個日期/時間和 它改變剩下的最後時間。

我無法輕易鏈接到文件的所有過渡版本,其中 就是爲什麼在這種情況下直接嘗試使用示例鏈接的文件不起作用 。如果代碼按照一步一步進行,代碼片段 ,一切都應該正常工作。對困惑感到抱歉。