Erlang,与列表foreach匹配

时间:2014-03-06 12:34:45

标签: erlang

我一直在Erlang为学校项目制作聊天应用程序,但我遇到了一个问题。我正在尝试使我的程序并发,为了这样做,我为每个通道发送的消息启动一个新线程。我这样做是使用列表:foreach,但我想确保我不会给输入频道的人留言。

request(State, {message, {UserID,UserPID}, Token}) ->
case catch lists:member({UserID,UserPID}, State#channel.users) of
    false ->
        {{error, user_not_joined}, State};
    true -> 
        spawn( fun() ->
        ListOfUsers = State#channel.users,
        UserPIDs = lists:map(fun ({_, V}) -> V end, ListOfUsers),
        %spawn( fun() ->end)
        lists:foreach( 
            fun(UserPID) -> ok end,
            fun(PID) ->
                spawn( fun() -> genserver:request(PID, {message_from_server, State#channel.name, UserID, Token}) end) 
            end, UserPIDs) end),
        {ok, State}
end;

我最想做的是匹配foreach中的UserPID。截至目前,我只收到警告:

channel.erl:39:警告:变量'UserPID'未使用 channel.erl:39:警告:变量'UserPID'在'fun'中隐藏

第3行很有趣(UserPID) - >好的结束,

干杯

2 个答案:

答案 0 :(得分:5)

legoscia的答案很好,但我补充一点,列表理解通常比lists:foreach更易于使用且阅读更简单。请注意,列表推导能够忽略基于子句的值。请考虑以下示例:

-module(filter).

-export([do/0]).

do() ->
    Values = lists:seq(1,10),
    IgnoreThisValue = 5,
    %% print all values unequal to IgnoreThisValue
    [io:format("Value: ~b~n", [Value]) ||
     Value <- Values, Value =/= IgnoreThisValue],
    ok.

在shell中运行它:

1> make:all([load]).
Recompile: filter
up_to_date
2> filter:do().     
Value: 1
Value: 2
Value: 3
Value: 4
Value: 6
Value: 7
Value: 8
Value: 9
Value: 10

关于代码的旁注:为什么每个进程都会产生一个线程?我假设您正在使用行为gen_server(如果我错了,请纠正我)。如果是这样,您应该考虑使用cast函数来发送消息。由于您没有检查genserver:request/2的结果,这可能是一个可行的选项,可以为您节省大量的流程。

答案 1 :(得分:3)

由于函数参数会影响现有变量,因此需要使用保护:

fun(PID) when PID =:= UserPID -> ok end