我正在努力学习其中一个模块中的记录。
我在我的代码之上定义了一条记录:
-record(user, {pid,
name,
nick}).
用少数几个词表示每个用户将被表示为具有自己的pid和其他字段的进程。
稍后在模块中,我正在执行以下操作:
Pid = UserPid,
GetUser = fun(X) ->
if X#user.pid =:= Pid -> true;
X#user.pid=/= Pid -> false
end
end,
User = lists:filter(GetUser, Users),
io:format("User pid is ~p~n",[User#user.pid]).
运行此代码我得到:
** exception error: {badrecord,user}
但如果我这样做:
io:format("User ~p~n",[User]).
打印
User [{user,<0.33.0>,name1,nick1}]
有人能说出我错过的东西吗?
由于
答案 0 :(得分:11)
问题是lists:filter
返回另一个列表,而不是单个元素。所以你基本上试图将列表视为记录。如果仔细查看
io:format("User ~p~n",[User])
%% User [{user,<0.33.0>,name1,nick1}]
您会注意到该语句包含在[]
中。这是一个清单。如果您只需要第一个用户
[First | Rest] = lists:filter(GetUser, Users)
如果您只想使用lists:map
:
UsersWithPid = lists:filter(GetUser, Users),
Pids = lists:map(fun(U) -> U#user.pid end, UsersWithPid).
现在Pids
是包含带有pid的用户的pids的列表。
答案 1 :(得分:7)
the lists:filter
函数的答案是正确的。
这就是我重写代码的方式:
-module(com).
-record(user, {pid,
name,
nick}).
-export([lookup/1]).
lookup(Pid) ->
Users = users(),
FilteredUsers = [User || #user{pid = P} = User <- Users, Pid =:= P],
lists:foreach(fun display/1, FilteredUsers).
display(User) ->
io:format("User name is ~p~n",[User#user.name]).
users() ->
User1 = #user{pid = 1, name = "Bob", nick = "bob"},
User2 = #user{pid = 2, name = "Alice", nick = "alice"},
User3 = #user{pid = 1, name = "Charlie", nick = "charlie"},
[User1, User2, User3].
我假设你可以有多个pids。如果你不这样做,你可以节省你自己的预备。
我相信在这种情况下使用list comprehensions会使代码更具可读性。另外,以下内容:
Pid = UserPid,
对我来说看起来不太有用......
答案 2 :(得分:4)
正如其他人所指出的那样,lists:filter/2
会返回一个列表,即使它只是一个元素。您正在寻找的函数是lists:keyfind/3
(在Erlang R14B03中,对于R13B04及更早版本,使用lists:keysearch/3
):
Eshell V5.8.4 (abort with ^G)
1> rd(user, {pid, name, nick}).
user
2> Users = [#user{pid = spawn(fun() -> ok end), name = name1, nick = nick1},
2> #user{pid = spawn(fun() -> ok end), name = name2, nick = nick2},
2> #user{pid = spawn(fun() -> ok end), name = name3, nick = nick3}].
[#user{pid = <0.34.0>,name = name1,nick = nick1},
#user{pid = <0.35.0>,name = name2,nick = nick2},
#user{pid = <0.36.0>,name = name3,nick = nick3}]
3> lists:keysearch(pid(0,35,0), #user.pid, Users).
{value,#user{pid = <0.35.0>,name = name2,nick = nick2}}
4> lists:keyfind(pid(0,35,0), #user.pid, Users).
#user{pid = <0.35.0>,name = name2,nick = nick2}
5> lists:keyfind(pid(0,99,0), #user.pid, Users).
false
lists:keyfind/3
是首选,因为它更简单。
仅使用#user.pid
会在pid
记录中返回字段#user
的位置:
6> #user.pid.
2
答案 3 :(得分:0)
您要显示的变量不是记录,而是包含其中一个元素的List。此列表中的元素是您想要的记录。考虑模式匹配lists:filter
in case语句的结果,如下所示:
case lists:filter(GetUser, Users) of [] -> %% user not found against that criteria..... [User] when is_record(User,user) -> %% user found. Do things here........ List -> %% are many things matching your criteria ? end, ...
另外,请记住true
的{{1}}子句。