erlang记录麻烦

发布于 2024-11-25 04:02:24 字数 765 浏览 5 评论 0原文

我正在努力处理我的一个模块中的记录。

我在代码顶部定义了一条记录:

-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}]

任何人都可以指出我缺少什么吗?

谢谢

I'am struggling with records in one of my modules.

I defined on top of my code a record as:

-record(user,  {pid,
                name,
                nick}).

in few words each user is going to be represented as process with its own pid and other fields.

Later on in the module I am doing the following:

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]).

Running this code I get:

** exception error: {badrecord,user}

But if I do:

io:format("User ~p~n",[User]).       

It prints

User [{user,<0.33.0>,name1,nick1}]

Can anyone point out what i am missing?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

黯然#的苍凉 2024-12-02 04:02:24

问题是 lists:filter 返回另一个列表,不是单个元素。所以你基本上是试图将列表视为记录。如果仔细查看输出,

io:format("User ~p~n",[User])
%% User [{user,<0.33.0>,name1,nick1}]

您会发现该语句被包裹在 [] 中。这是一个清单。如果您只需要第一个用户使用

[First | Rest] = lists:filter(GetUser, Users)

如果您只想要 pid 使用 lists:map< /code>

UsersWithPid = lists:filter(GetUser, Users),
Pids = lists:map(fun(U) -> U#user.pid end, UsersWithPid).

现在 Pids 列出了具有 pid 的用户的 pid。

The problems is that lists:filter returns another list, not a single element. So you are basically trying to treat a list as a record. If you look carefully in the output of

io:format("User ~p~n",[User])
%% User [{user,<0.33.0>,name1,nick1}]

you will notice that the statement is wrapped in []. It's a list. If you need just the first user use

[First | Rest] = lists:filter(GetUser, Users)

If you only want the pids use lists:map:

UsersWithPid = lists:filter(GetUser, Users),
Pids = lists:map(fun(U) -> U#user.pid end, UsersWithPid).

Now Pids is list with the pids of the users with pid.

你的往事 2024-12-02 04:02:24

Emil 关于 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].

我假设你可以有多个 pid。如果不这样做,您可以节省自己的 foreach 。

我相信在这种情况下使用 列表推导式 会使代码更具可读性。另外,以下内容:

Pid = 用户Pid,

对我来说看起来不太有用......

Emil's answer about the lists:filter function is correct.

This is how I would rewrite your code, though:

-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].

I'm assuming you can have multiple pids. If you don't, you can save yourself the foreach.

I believe that using list comprehensions in this case makes the code much more readable. Also, the following:

Pid = UserPid,

doesn't look very useful to me...

痴骨ら 2024-12-02 04:02:24

正如其他人指出的那样,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

As others have pointed out, lists:filter/2 returns a list, even if it's just a single element. The function you're looking for is lists:keyfind/3 (in Erlang R14B03, for R13B04 and earlier, use 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 is preferred because it's simpler.

Using only #user.pid returns the position of the field pid in the #user record:

6> #user.pid.
2
还如梦归 2024-12-02 04:02:24

您尝试显示的变量不是一条记录,而是一个其中包含一个元素的列表。该列表中的元素是您想要的记录。考虑与您的 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,
...

另外,请记住 if 语句true 子句。

the variable you are trying to display is not a record but rather, a List with one element inside it. The element inside this list is the record you want. Consider pattern matching the result of your lists:filter in case statement like this:

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,
...

Also, remember the true clause of the if statement.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文