0

私はこのチュートリアルに従っていて、event.erlをコンパイルして、それに従って実行しようとしました。

6> c(event).
{ok,event}
7> rr(event, state).
[state]
8> spawn(event, loop, [#state{server=self(), name="test", to_go=5}]).
<0.60.0>
9> flush().
ok
10> flush().
Shell got {done,"test"}
ok
11> Pid = spawn(event, loop, [#state{server=self(), name="test", to_go=500}]).
<0.64.0>
12> ReplyRef = make_ref().
#Ref<0.0.0.210>
13> Pid ! {self(), ReplyRef, cancel}.
{<0.50.0>,#Ref<0.0.0.210>,cancel}
14> flush().
Shell got {#Ref<0.0.0.210>,ok}
ok

しかし、代わりにこのエラーが発生するため、ステップ8を通過できないようです。

7> spawn(event, loop, [#state{server=self(), name="test", to_go=5}]).

=ERROR REPORT==== 14-Feb-2013::11:14:38 ===
Error in process <0.51.0> with exit value: {function_clause,[{event,loop,[{state,<0.32.0>,"test",5}],[{file,"event.erl"},{line,35}]}]}

<0.51.0>

以下はevent.erlです

-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)].

編集:私はこれから引数を追加することによって関数ループを変更しようとしました

loop(S = #state{server=Server, to_go=[T|Next]}) ->

to this 

loop(S = #state{server=Server,name=EventName, to_go=[T|Next]}) ->

それでもコンパイルされますが、機能しません。同じエラーです...タプルが一致していないのではないかと思いました。その後、それは議論to_go=[T|Next]}が正しくないことに発展するだけです。

4

3 に答える 3

2

問題は、loop / 1句が#stateパラメーターをアンパックして、to_goがリストとパターン一致するようにすることだと思います(つまり、to_go = [T | Next])。ただし、5(to_go = 5)を渡すと、[T | 次へ]したがって、loop / 1は一致せず、一致する関数句はありません。

loop(#state{server=self(), name="test", to_go=5})
于 2013-02-14T17:42:20.690 に答える
1

Erlangプロセスイベントエラーと同じ問題です。、および関数は、形式の時間引数を予期しているstart/2ため、。を使用して呼び出すと失敗します。この関数は、のフィールドが秒として解釈される整数のリストであることを想定しており、それぞれに対してaを実行して合計時間を待機します。このサーバーの目標は、Erlangがで直接実行できるよりも長い時間待機できるようにすることです。start_link/2time_to_go/1{{Year,Month,Day},{Hour,Minute,Second}}5loop/1to_go#state{}receive...afterreceive...after

このtime_to_go/1関数は、現在から引数として入力された日付/時刻までの秒数を計算し、それを秒のリストに分割します。秒のリストは、最大サイズが処理できる秒数を超えるものはありませんreceive...after

于 2013-02-14T23:03:25.683 に答える
1

この式:

8> spawn(event, loop, [#state{server=self(), name="test", to_go=5}]).

チュートリアル全体で開発されているため、以前のバージョンのコードに適用されます。私がそれを正しく読んでいるなら、これは正しい呼び出しであるはずです:

19> event:start("Event", 0).
于 2013-02-14T18:11:33.107 に答える