2011-07-21 14 views
6

मैं अपने मॉड्यूल में से एक में रिकॉर्ड के साथ संघर्ष कर रहा हूं।erlang रिकॉर्ड परेशानी

-record(user, {pid, 
       name, 
       nick}). 
कुछ शब्दों में

प्रत्येक उपयोगकर्ता जा रहा है अपने आप ही पीआईडी ​​और अन्य क्षेत्रों के साथ प्रक्रिया के रूप में प्रतिनिधित्व करने वाला:

मैं अपने कोड एक रिकार्ड के रूप में की चोटी पर परिभाषित किया।

बाद में मॉड्यूल में मैं कर रहा हूँ निम्नलिखित:

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

क्या कोई यह बता सकता है कि मैं क्या खो रहा हूं?

धन्यवाद

उत्तर

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

मैं यह सोचते कर रहा हूँ आप एक से अधिक पीआईडी ​​की हो सकता है:

यह कैसे मैं अपने कोड है, हालांकि फिर से लिखने होता है। यदि आप नहीं करते हैं, तो आप खुद को foreach बचा सकते हैं।

मेरा मानना ​​है कि इस मामले में list comprehensions का उपयोग करके कोड को और अधिक पठनीय बनाता है।इसके अलावा, निम्नलिखित:

Pid = UserPid,

मेरे लिए बहुत उपयोगी नहीं लगती है ...

+0

+1 idiomatic Erlang का बहुत साफ उदाहरण। –

+3

मैं करूँगा [यू || यू <- उपयोगकर्ता, यू # user.pid =: = पी] '। –

+0

@ एडम लिंडबर्ग: +1। और भी पठनीय। –

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 पीआईडी ​​के साथ उपयोगकर्ताओं की पीआईडी ​​के साथ सूची है।

+2

ध्यान दें कि [पहले, बाकी] ठीक दो तत्वों के साथ एक सूची के खिलाफ मिलान कर देंगे। आप शायद चाहते हैं: [पहले | बाकी]। या, यदि आप वास्तव में एक परिणाम की उम्मीद कर रहे हैं: [पहले]। –

+1

@ रॉबर्टो - सही, धन्यवाद। –

0

जिस चर को आप प्रदर्शित करने का प्रयास कर रहे हैं वह रिकॉर्ड नहीं है बल्कि इसके अंदर एक तत्व के साथ एक सूची है। इस सूची के अंदर तत्व वह रिकॉर्ड है जिसे आप चाहते हैं। इसके अलावा

 
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 statement की true खंड: पैटर्न इस तरह से अपनी lists:filter मामले में बयान का नतीजा मिलान पर विचार करें।

4

के रूप में अन्य लोगों ने बताया है, lists:filter/2 सूची लौटाता है, भले ही यह है सिर्फ एक ही तत्व। समारोह आप देख रहे हैं (R13B04 के लिए Erlang R14B03 में, और पहले, lists:keysearch/3 का उपयोग करें) lists:keyfind/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 रिटर्न #user रिकॉर्ड में क्षेत्र pid की स्थिति का उपयोग करना:

6> #user.pid. 
2 
+0

+1 प्राप्त करने का प्रयास कर रहा था #user रिकॉर्ड में पिड। – justin