Erlang模式匹配接收的记录列表

时间:2011-09-05 13:19:08

标签: functional-programming erlang pattern-matching

我正在尝试为我的应用程序的一部分创建通用接收,该接收需要在不同时间等待多次更新。
这是它无法正常工作的原型。

receive_info([])->[];
receive_info([RequiredInfo|RestRequiredInfos]) ->
  receive
    RequiredInfo -> [ RequiredInfo | receie_info(RestRequiredInfos)];
  end.

它被称为

[UserInfo, ContextInfo] = receive_info([#userinfo{},#contextinfo{}]),

所以,我正在尝试的是发送一个应该匹配的记录类型列表,我希望收到一份记录列表。
不确定这是否可行,因为记录将其字段设置为undefined,并且模式匹配不起作用,例如:

Trying to receive {user_info,undefined}
Other clause: instead {user_info,12} received

修改
由于@Adam Lindberg提供的is_record版本对我不起作用,我采用了相同的做法,我最终得到了:

receive_infos([]) -> [];
receive_infos([Rec|Records]) ->
receive
    %% Guard expression that compares first element in record with supplied record tag
    Record when element(1, Record) =:= Rec -> 
        [ Record | receive_infos(Records)]
end.

3 个答案:

答案 0 :(得分:3)

如果您将其重写为:

receive_info([]) -> [];
receive_info([Rec|Records]) ->
    receive
        Msg when is_record(Msg, Rec) ->
            [Msg|receive_info(Records)];
    end.

并将其命名为:

receive_info([userinfo, contextinfo])

它会做你想要的。

答案 1 :(得分:2)

我认为你的最后一个答案是正确的,但你可以再添加一张支票,以确保你获得正确尺寸的记录:

receive_infos([]) -> [];
receive_infos([Rec|Records]) ->
receive
    %% Guard expression that compares first element in record with supplied record tag
    Record when element(1, Record) =:= element(1, Rec), size(Record) =:= size(Rec) -> 
        [ Record | receive_infos(Records)]
end.

由于大小和第一个元素原子是关于记录的所有内容,这可能与你要做的一样好。

或者可以说更直接,接受这两个作为论点:

receive_infos([]) -> [];
receive_infos([{Name, Size}|Records]) ->
receive
    %% Guard expression that compares first element in record with supplied record tag
    Record when element(1, Record) =:= Name, size(Record) =:= Size -> 
        [ Record | receive_infos(Records)]
end.

并将其命名为

receive_infos([{foo, record_info(size, foo)} | etc. ])

答案 2 :(得分:1)

有几件事。您正在尝试将RequiredInfo(默认记录数据)与RequiredInfo(作为消息发送的已填充记录数据)进行匹配。因此,您只希望获得您已经拥有的数据,我认为这可能不是您想要的。你在receie_info上也有一些拼写错误。

如果我想用已收到的填充记录填写默认记录列表,并且必须收到所有记录或一切都失败,我可能会这样做。

fill_records(List)   -> fill_records(List,length(List)).
fill_records(List,0) -> List;
fill_records(List,N) ->
    receive Rec -> fill_records(lists:keyreplace(element(1,Rec),1,List,Rec),N-1)
    after 5000 -> {error,timeout} end.

您应该通过防止接收相同记录类型或不需要的记录类型的多个实例来保护这一点,具体取决于周围的系统。

您当然也可以创建一个接收循环,您只需定义期望的消息数,或者查看gen_fsm或gen_server及其内部状态和消息处理。