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

AFAIK,“ -spec ”仅用于文档目的,不会在运行时检查您的类型。

正如您正确地说的那样,本身没有类型检查,但是您可以混合使用模式匹配和守卫来使事情失败。尽管如此,这都是防御性编程,你应该让它崩溃,并让主管树重启任何需要重启的东西。日志和崩溃报告应该为您提供足够的信息以了解问题所在并采取相应措施。

于 2012-06-25T16:04:08.533 回答
1

好吧,如果您需要的只是一些基本类型(可能还有范围)检查,您可以使用警卫

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

不幸的是,由于一些限制(例如,守卫必须没有任何副作用),没有办法编写自己的守卫函数。

于 2012-06-25T16:02:10.130 回答