1

私は基本的にこのサイトのチュートリアルに従っていますErlang:並行アプリケーションの設計を学び、次のコマンドで以下のコードを実行しようとしましたが、48行目でエラーが発生しました。問題はありますが、運がありません。私はWindowsXPSP3を使用しています。

9> c(イベント)。

{ok、event}

10> f()。

わかった

11> event:start( "Event"、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"}、{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)].
4

2 に答える 2

3

ファイアウォールが影響を与えないように、マシン上で純粋にローカルで実行されています。

問題はあなたがそれを始めたときにあなたが与えた2番目の議論です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引数に一致する句が関数定義になかったことを意味するエラーであると言います。event:time_to_go/1また、失敗したのは48行目の関数であり、引数を指定して呼び出されたことも示しています0

関数time_to_go/を見ると、引数が2要素のタプルであることが期待されていることがわかります。各要素は3要素のタプルです。

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

この引数の構造はです{{Year,Month,Day},{Hour,Minute,Second}}。この引数を逆方向にたどると、、、への引数が。への3番目の引数であるところtime_to_go/から呼び出されます。もうすぐそこにあります。これが、プロセスが生成した関数です(およびstart_link / 2 init / 3 start/2`。init/3time_to_go/1DateTimeinit/3init/3start/2) and the 3rd argument tois the second argument to

したがって、呼び出すevent:start("Event",0).と、新しいpeocess0の呼び出し関数に渡されるのはここです。time_to_go/1そして、フォーマットが間違っています。あなたはそれを次のようなもので呼ぶべきですevent:start("Event", {{2013,3,24},{17,53,62}}).

于 2013-02-10T02:46:11.573 に答える
1

rvirdingの答えに背景を追加すると、エラーが発生します。これは、私の知る限り、この例は最終的なコードスニペットまで機能するためです。このnormalize関数が最初に使用され、問題に対処します。次に、上記の質問の例の直後の段落には、次のように書かれています。

そしてそれは動作します!イベントモジュールで最後に煩わしいのは、残り時間を秒単位で入力する必要があることです。Erlangのdatetime()などの標準形式を使用できれば、はるかに良いでしょう{{Year, Month, Day}, {Hour, Minute, Second}}。コンピューターの現在の時刻と挿入した遅延の差を計算する次の関数を追加するだけです。

次のスニペットは、日付/時刻のみを取得し、それを残りの最後の時刻に変更するコードビットを紹介します。

ファイルのすべての移行バージョンに簡単にリンクすることはできませんでした。そのため、この場合、リンクされたファイルを例で直接試してみるのは簡単ではありません。コードを段階的に、スニペットごとに実行すると、すべてが正常に機能するはずです。混乱させて申し訳ありません。

于 2013-04-16T13:36:12.043 に答える