2009-01-15 11 views
9

मैं एक एरलांग सिस्टम विकसित कर रहा हूं और इस तथ्य के साथ पुन: संक्रमित समस्याएं कर रहा हूं कि रिकॉर्ड संकलित-समय प्री-प्रोसेसर मैक्रोज़ (लगभग) हैं, और वे रनटाइम पर हेरफेर नहीं हो सकते हैं ... मूल रूप से, मैं एक संपत्ति पैटर्न के साथ काम कर रहा हूं, जहां फ्रंट-एंड (एएस 3) पर वस्तुओं के लिए रन-टाइम पर गुण जोड़े जाते हैं। आदर्श रूप से, मैं इसे एरलैंग पक्ष की एक सूची के साथ प्रतिबिंबित करता हूं, क्योंकि यह एक मौलिक डेटा प्रकार है, लेकिन फिर क्यूसीएल [ईटीएस टेबल पूछने के लिए] में रिकॉर्ड का उपयोग करना संभव नहीं होगा, इसलिए मुझे विशेष रूप से कहना होगा कि कौन सी रिकॉर्ड संपत्ति I पूछना चाहता हूं ... मेरे पास बड़े पैमाने पर तालिका में कम से कम 15 कॉलम हैं, इसलिए उन्हें एक विशाल स्विच स्टेटमेंट (केस एक्स) में सूचीबद्ध करना सिर्फ सादा बदसूरत है।एरलांग और रन-टाइम रिकॉर्ड सीमाएं

क्या किसी के पास कोई विचार है कि इसे कैसे हल किया जाए? शायद पैटर्न मिलान (QLC के लिए) में उपयोग के लिए उपयुक्त हस्ताक्षर के साथ tuples बनाने के लिए कुछ अंतर्निहित कार्यों?

धन्यवाद

+0

यदि आप एक psuedo-code उदाहरण देते हैं जो आप करना चाहते हैं तो यह मदद करेगा। – archaelus

उत्तर

0

मुझे यकीन है कि मैं पूरी तरह से आपकी समस्या समझ में नहीं कर रहा हूँ, लेकिन मैं ज्यादातर मामलों में proplists को रिकॉर्ड से चले गए हैं। वे अधिक लचीले और बहुत धीमे हैं। (डी) Iets का उपयोग मैं आमतौर पर मोटे चयन के लिए कुछ रिकॉर्ड फ़ील्ड का उपयोग करता हूं और फिर विस्तृत चयन के लिए शेष रिकॉर्ड्स पर प्रोपलिस्ट की जांच करता हूं।

+0

प्रस्तावसूची आसान हैं यदि आपको कभी भी पैटर्न-मिलान करने की आवश्यकता नहीं है (मेरा मुख्य उपयोग विकल्प सूची है 'proplists: get_value/3' आपको एक मान प्राप्त करने या एक ऑपरेशन में डिफ़ॉल्ट का उपयोग करने की अनुमति देता है। यदि आप कभी पैटर्न बनाना चाहते हैं हालांकि, आपको नामित स्लॉट पहुंच के लिए रिकॉर्ड की आवश्यकता है। – archaelus

4

ऐसा लगता है कि आप get_record_field(Field, SomeRecord) जैसे कुछ करने में सक्षम होना चाहते हैं, जहां Field उपयोगकर्ता इंटरफ़ेस कोड द्वारा रनटाइम पर निर्धारित किया गया है।

आप सही हैं कि आप मानक एरलांग में ऐसा नहीं कर सकते हैं क्योंकि रिकॉर्ड और record_info फ़ंक्शन का विस्तार और संकलन समय पर समाप्त हो गया है।

कुछ ऐसे समाधान हैं जिनका मैंने उपयोग किया है या देखा है। मेरे समाधान इस प्रकार है: rec_test.erl


तुम भी विस्तार कर सकते हैं:

%% Retrieves the value stored in the record Rec in field Field. 
info(Field, Rec) -> 
    Fields = fields(Rec), 
    info(Field, Fields, tl(tuple_to_list(Rec))). 

info(_Field, _Fields, []) -> erlang:error(bad_record); 
info(_Field, [], _Rec) -> erlang:error(bad_field); 
info(Field, [Field | _], [Val | _]) -> Val; 
info(Field, [_Other | Fields], [_Val | Values]) -> info(Field, Fields, Values). 

%% The fields function provides the list of field positions 
%% for all the kinds of record you want to be able to query 
%% at runtime. You'll need to modify this to use your own records. 
fields(#dns_rec{}) -> fields(dns_rec); 
fields(dns_rec) -> record_info(fields, dns_rec); 
fields(#dns_rr{}) -> fields(dns_rr); 
fields(dns_rr) -> record_info(fields, dns_rr). 

%% Turns a record into a proplist suitable for use with the proplists module. 
to_proplist(R) -> 
    Keys = fields(R), 
    Values = tl(tuple_to_list(R)), 
    lists:zip(Keys,Values). 

यह है कि संकलित का एक संस्करण यहाँ उपलब्ध है (उदाहरण के inet_dns.hrl से #dns_rec और #dns_rr रिकॉर्ड के क्रम पहुँच देता है) ets:select/2 या mnesia:select/2 के साथ उपयोग के लिए मिलान के लिए गतिशील पीढ़ी के लिए यह गतिशील फ़ील्ड लुकअप नीचे दिखाया गया है:

%% Generates a matchspec that does something like this 
%% QLC psuedocode: [ V || #RecordKind{MatchField=V} <- mnesia:table(RecordKind) ] 
match(MatchField, RecordKind) -> 
    MatchTuple = match_tuple(MatchField, RecordKind), 
    {MatchTuple, [], ['$1']}. 

%% Generates a matchspec that does something like this 
%% QLC psuedocode: [ T || T <- mnesia:table(RecordKind), 
%%      T#RecordKind.Field =:= MatchValue] 
match(MatchField, MatchValue, RecordKind) -> 
    MatchTuple = match_tuple(MatchField, RecordKind), 
    {MatchTuple, [{'=:=', '$1', MatchValue}], ['$$']}. 

%% Generates a matchspec that does something like this 
%% QLC psuedocode: [ T#RecordKind.ReturnField 
%%     || T <- mnesia:table(RecordKind), 
%%      T#RecordKind.MatchField =:= MatchValue] 
match(MatchField, MatchValue, RecordKind, ReturnField) 
    when MatchField =/= ReturnField -> 
    MatchTuple = list_to_tuple([RecordKind 
      | [if F =:= MatchField -> '$1'; F =:= ReturnField -> '$2'; true -> '_' end 
       || F <- fields(RecordKind)]]), 
    {MatchTuple, [{'=:=', '$1', MatchValue}], ['$2']}. 


match_tuple(MatchField, RecordKind) -> 
    list_to_tuple([RecordKind 
      | [if F =:= MatchField -> '$1'; true -> '_' end 
       || F <- fields(RecordKind)]]). 

उल्फ वाइगर ने एक parse_transform, Exprecs भी लिखा है, जो आपके लिए स्वचालित रूप से कम या ज्यादा करता है। मैंने कभी कोशिश नहीं की है, लेकिन उल्फ का कोड आमतौर पर बहुत अच्छा होता है।


1

मैं इस समस्या (विकास) पार्स को बदलने के उपकरणों का उपयोग .hrl फ़ाइलों सहायक कार्यों पढ़ सकते हैं और उत्पन्न करने के लिए हल।

मैंने Trap Exit पर tutorial लिखा था।

हम मैच चश्मा उत्पन्न करने के लिए हर समय इसका उपयोग करते हैं। सौंदर्य यह है कि आपको विकास समय की वर्तमान स्थिति के बारे में कुछ भी जानने की आवश्यकता नहीं है विकास समय पर।

हालांकि एक बार जब आप उत्पादन में होते हैं तो चीजें बदल जाती हैं!यदि आपका रिकॉर्ड किसी तालिका का आधार है (तालिका में किसी फ़ील्ड की परिभाषा के विपरीत) तो एक अंतर्निहित रिकॉर्ड बदलना अधिक कठिन है (इसे हल्के ढंग से डालने के लिए!)।