1

私が理解していることから、erlangで送信されるメッセージをタイプチェックする方法はありません。

次の受信ループでモジュールを開始するとします。

loop(State) ->
    receive 
    {insert, _} ->
        io:fwrite("insert\n",[]),
        loop(State);
    {view, _} ->
        io:fwrite("view\n", []),
        loop(State)
    after 10000 ->
        ok
    end.

人々がプロセスに送信しているものを確認する方法はありません。また、そのタイプが安全かどうかを確認する方法もありません。

簡単な回避策はありますか?

私が思いついたのは、次のように呼び出されるモジュールの関数を使用することです。

send_insert(Message) ->
    whereis(my_event_handler) !  {insert, Message},
    ok.

このようにして、少なくとも-spec send_insert(string()) -> ok.仕様をモジュールに追加できます。これで、少なくともエラーをモジュールに限定しました。

メッセージのタイプチェックを行うためのより標準的な方法はありますか?

4

4 に答える 4

4

あなたの問題を解決する保安官プロジェクトがあります。typespecsで定義されているタイプに対して値をチェックするために使用できます。

于 2012-06-25T16:17:33.567 に答える
3

send_insertモジュールのように、プロセスにメッセージを送信するだけの関数を使用することは、型チェックだけでなく、良い習慣だと思います。将来的にメッセージ形式を変更する必要がある場合は、その関数と場合によってはその呼び出し元を変更するだけでよいことがわかります。これは、特定の形式のメッセージを送信するすべての場所を見つけるよりも簡単に追跡できます。一部のプロセス(コードをリファクタリングしているプロセスである場合とそうでない場合があります)。また、呼び出し元はモジュール名を指定する必要があるため、コードはもう少し自己文書化されます。そのメッセージがどのプロセスに進むべきかがわかります。

(ところで、次のwhereis(my_event_handler) ! {insert, Message}ように書くことができますmy_event_handler ! {insert, Message}。)

于 2012-06-25T17:17:34.887 に答える
1

さて、必要なのが基本的なタイプ(そしておそらく範囲)のチェックだけである場合は、ガードを使用できます:

receive 
    {insert, Message} when is_list(Message) ->
        io:fwrite("insert\n",[]),
        loop(State);

残念ながら、いくつかの制約があるため(たとえば、ガードには副作用がない必要があります)、独自のガード関数を作成する方法はありません。

于 2012-06-25T16:02:10.130 に答える
1

AFAIK、 " -spec "は文書化のみを目的としており、実行時にタイプをチェックしません。

あなたが正しく言うように、それ自体はタイプチェックはありませんが、パターンマッチングとガードを組み合わせて失敗させることができます。それでも、これはすべて防御的なプログラミングであり、クラッシュさせて、再起動が必要なものはすべてスーパーバイザーツリーに再起動させる必要があります。ログとクラッシュレポートは、何がうまくいかなかったかを知り、それに応じて行動するのに十分な情報を提供するはずです。

于 2012-06-25T16:04:08.533 に答える