2010-09-29 17 views
5

मैं Erlang शैली खोज निकाला है लूप: कार्यों है कि सभी "चर भिन्न नहीं" ले के साथ पूंछ-प्रत्यावर्तन:गिनती (? कैसे मैं एक चर को बढ़ा देते है)

%% does something, 80 bytes at a time 
loop(Line, File) -> loop(Line, File, 0). 
loop(Line, File, Count) -> 
    do_something(Line, Count), 
    case file:read(File, 80) of 
     {ok, Line2} -> loop(Line2, File, Count + 1); 
     eof -> file:close(File); 
     {error, Reason} -> {error, Reason} 
    end. 

लेकिन, एरलांग में काउंटर बढ़ाने का सबसे अच्छा तरीका क्या है? अधिकांश प्रोग्रामिंग भाषाओं में, जिस तरह से आप चीजों की गिनती करते हैं वह एक चर (यानी count += 1;) बढ़ाकर होता है। Erlang के चर अलग-अलग नहीं होते हैं, इसलिए हमें रचनात्मक होना है। सौभाग्य से, हमारे पास विकल्प हैं ...

हम अपने कार्यों के साथ काउंटर वैरिएबल पास कर सकते हैं, और प्रत्येक फ़ंक्शन कॉल के साथ इसे बढ़ा सकते हैं। हम गणना करने के लिए प्रक्रिया शब्दकोश का उपयोग कर सकते हैं, और इसे बढ़ाने के लिए get और put का उपयोग कर सकते हैं। हम ईटीएस, प्रक्रियाओं के लिए स्थानीय डेटा भंडारण का उपयोग कर सकते हैं। हम काउंटर प्रक्रिया (!!!) का उपयोग कर सकते हैं:

loop(Count) ->        
    receive         
     { incr } -> 
      loop(Count + 1);    
     { report, To } ->      
      To ! { count, Count },    
      loop(Count)       
    end.          

incr(Counter) -> 
    Counter ! { incr }. 

get_count(Counter) ->  
    Counter ! { report, self() }, 
    receive 
     { count, Count } -> Count 
    end. 

मुझे यकीन है कि दायरे के आधार पर अन्य तरीके भी हैं। Erlang में एक चर बढ़ाने के लिए "सर्वोत्तम अभ्यास" क्या माना जाता है?

+0

यह प्रश्न उपयोग के बिना बहुत सार्थक नहीं है। सूची में चीजों को गिनने के लिए आप 'सूचियां: फ़ोल्डल' कर सकते हैं (या' फ़िल्टर' + 'लंबाई')। यदि आप 'gen_server' कॉल की गणना कर रहे हैं, तो आप इसे अपने सर्वर के राज्य के साथ आसानी से करते हैं। – Dustin

+0

मैं पहले ही PHP खो रहा हूं ... स्थिर $ i; $ i ++; – Rolf

उत्तर

3

यह सब इस बात पर निर्भर करता है कि आप किस काउंटर का उपयोग कर रहे हैं। Q सिस्टम द्वारा प्रबंधित संदेशों की संख्या की तरह वैश्विक कुछ भी ets: update_counter का उपयोग करना चाहिए। यदि यह वैश्विक नहीं है तो मैं आमतौर पर इसे आपके द्वारा दिखाए गए पैरामीटर में शामिल करता हूं।

9

प्रक्रिया शब्दकोश का उपयोग न करें।

'सामान्य' पाश है कि आप (यानी एक for पाश या एक do while) उम्मीद कर रहे हैं आमतौर पर Erlang में एक पुनरावर्ती समारोह में कार्यान्वित किया जाता, इसलिए यदि आप एक 'सामान्य' काउंटर incrementing रहे समारोह में ऐसा कहता है की तरह आपको बताएंगे ऊपर शीर्ष।

प्रक्रिया शब्दकोश का उपयोग न करें।

यदि आप चूक गए हैं, तो क्या मैं केवल यह इंगित कर सकता हूं कि आपको प्रक्रिया शब्दकोश का उपयोग नहीं करना चाहिए।

+3

इसके अलावा, प्रक्रिया शब्दकोश का उपयोग न करें। –

+2

फिर भी अजीब बात यह है कि एरलंग/ओटीपी वितरण में लगभग हर एप्लिकेशन में प्रक्रिया शब्दकोश का उपयोग किया जाता है। 'Inets' की तरह। या 'ऑर्बर'। या 'डॉकबिल्डर'। या 'आईसी'। या 'मेगाको'। या 'टीवी'। या 'cosnotification'। या 'eunit'। या 'reltool'। या 'कंपाइलर'। या 'erts'। या 'test_server'। या 'एपमन'। या 'एसएसएच '। या 'डीबगर'। या 'कर्नेल'। या 'जीएस'। या 'os_mon'। या 'पमन'। या 'stdlib'। या 'अवधारणा'। या 'xmerl'। या 'asn1'। या 'मिनेसिया'। या 'common_test'। या 'पार्सेटूल'। या 'डायलज़र'। या ... यदि समुदाय संदेश पर रहा तो "कोई प्रक्रिया शब्दकोश" ज्ञापन पर विश्वास करना आसान होगा। –

+3

सामान्य नियम यह है कि "यदि आपको आश्चर्य है कि आपको प्रक्रिया शब्दकोश का उपयोग करना चाहिए, तो आपको इसका उपयोग नहीं करना चाहिए" और "आपको पता चलेगा कि आपको इसकी आवश्यकता कब होगी।" निष्पक्ष होने के लिए, वैध प्रक्रिया शब्दकोष उपयोग करते समय, उनमें से अधिकतर को 'incrementing चर' के साथ नहीं करना है, बल्कि जहां तक ​​मुझे पता है, 'भंडारण प्रक्रिया मेटाडाटा' के साथ नहीं करना है। –

0

काउंटर बढ़ाने का मानक तरीका आपके पहले उदाहरण में है। कॉल में एक चर जोड़कर और इसे बढ़ाना। मुझे लगता है कि आप लूपों की कमी और मूल्यों को अपडेट करने की संभावना से भ्रमित हो जाते हैं।

ध्यान दें कि:

repeat(Times) when Times >= 0 -> repeat(0, Times). 

repeat(Times, Times) -> done; 
repeat(N, Times) -> 
    do_a_side_effect, 
    repeat(N + 1, Times). 

को संकलित करता है (कम या ज्यादा) के रूप में एक ही बात (छद्म कोड में):

repeat(Times) -> 
    while (N < Times) { 
    do_a_side_effect 
    N++ 
    } 
    return done 

आप परिणाम जमा करने के लिए वहाँ क्या करने के लिए तरीके हैं चाहते हैं वह भी।

या तो सूचियों पैकेज का उपयोग करें या परिणाम अपने आप को जमा:

loop(File) -> 
    {ok, Fd} = file:open(File), 
    loop(Fd, 0, []). 

loop(Fd, Count, Acc) -> 
    case file:read(Fd, 80) of 
    {ok, Line} -> 
     Result = do_something(Line, Count), 
     loop(Fd, Count + 1, [Result | Acc]); 
    eof -> 
     file:close(File), 
     {Count, lists:reverse(Acc)}; 
    {error, Reason} -> {error, Reason} 
    end. 

या कुछ इसी तरह अपने उदाहरण पर आधारित है।

संपादित करें: वापसी मूल्य के हिस्से के रूप में भी गणना की गई, क्योंकि यह महत्वपूर्ण प्रतीत होता था।

2

मुझे लगता है कि आपने इससे बड़ा सौदा किया है, जबकि आप इसे और अधिक आसान बना सकते हैं।
Erlang में पाश के लिए की इस कार्यान्वयन पर विचार करें:

for(Max, Max, F) -> [ F(Max) ]; 
for(I, Max, F) -> [ F(I) | for(I+1, Max, F) ]. 

जबकि F समारोह है कि आप मूल्यों Max को I के लिए यह परिणाम सहेजना चाहते है।
क्या समझना आसान नहीं है?

संबंधित मुद्दे