2010-05-06 12 views
10

मैं सिर्फ हास्केल की शुरुआत कर रहा हूं, लेकिन मुझे मिले सभी ऑनलाइन ट्यूटोरियल से मुझे लगता है कि सशर्त नियंत्रण कथन करने के लिए एक स्वीकार्य तरीका नहीं है। मैंने देखा है कि-और, गार्ड, और पैटर्न मिलान, लेकिन वे सभी एक ही चीज़ को पूरा करने लगते हैं। क्या बाकी के मुकाबले एक आम तौर पर स्वीकार्य/तेज/अधिक कुशल तरीका है?हास्केल में नियंत्रण कथन?

+2

'केस-ऑफ' को न भूलें :) – kennytm

+1

'केस' पैटर्न-मिलान है। – Chuck

+4

उन सभी तकनीकों 'केस' के लिए संकलित हैं। 'केस' मौलिक नियंत्रण तंत्र है - एक पैटर्न के आधार पर प्रेषण। गार्ड, पैटर्न इत्यादि केवल चीनी हैं। –

उत्तर

10

क्या बाकी के मुकाबले एक आम तौर पर स्वीकार्य/तेज़/अधिक कुशल तरीका है?

गार्ड (या जटिल) सिंटैक्टिक चीनी हैं, तो इसके बाद पैटर्न मिलान के बाद। यदि -0-0 caseBool से अधिक के लिए सिंटेक्टिक चीनी है। तो ये चीजें ज्यादातर समान रूप से कुशल हैं।

लेकिन यहाँ एक अवलोकन है: यह एक बूलियन अभिव्यक्ति क्या एक पैटर्न मैच के साथ कुशल है साथ अकुशलता से करने के लिए अक्सर आसान है। शुरुआत हास्केल प्रोग्रामर के एक पसंदीदा उदाहरण

length xs == 0 

जो xs की लंबाई के अनुपात लागत, जहां

case xs of { [] -> True; _:_ -> False } 

निरंतर समय लागत लिखने के लिए है।

क्या चल रहा है यह देखने के लिए एक और सटीक तरीका यह है कि (अनुपस्थित फैंसी एक्सटेंशन जैसे पैटर्न पैटर्न), पैटर्न पैटर्न की सबसे बुरी स्थिति लागत बायीं तरफ — पर दिखाई देने वाले रचनाकारों की संख्या के समान है। महंगे और छोटे दोनों पैटर्न पैटर्न नहीं लिख सकते हैं। इसके विपरीत, एक बूलियन अभिव्यक्ति का आकार आपको कुछ भी बताता है कि इसका मूल्यांकन करने के लिए क्या खर्च होता है। इस अर्थ में, और इस अर्थ में, पैटर्न मिलान मिलान-फिर-या गार्ड से सस्ता है।

शुरुआती लोगों के लिए एक अच्छा ह्युरिस्टिक जहां भी संभवतः आप मिलान कर सकते हैं पैटर्न पैटर्न का उपयोग करें। जैसे ही आपको अधिक अनुभव मिलता है, आप अपना दृष्टिकोण परिशोधित कर सकते हैं।

+0

(बेशक, आपको 'xs' खाली है या नहीं, यह जांचने के लिए आपको 'शून्य xs' का उपयोग करना चाहिए।) – kennytm

+1

@ केनी अगर मेरे पास मेरे प्रत्येक छात्र के लिए एक डॉलर था जिसने' शून्य xs 'के बजाय' लंबाई xs == 0' लिखा था , मुझे साल के लिए कॉफी में रखने के लिए पर्याप्त होगा :-) –

4

ठीक है, मुझे नहीं पता कि "नियंत्रण कथन" के संदर्भ में सोचना हैस्केल में इसके बारे में जाने का सबसे अच्छा तरीका है। उस ने कहा, यह ज्यादातर अंत में मिलान पैटर्न के लिए आता है; if ... then ... else जैसे बूलियन सशर्त उदाहरण के लिए Bool के लिए रचनाकारों पर पैटर्न मिलान के संदर्भ में परिभाषित किया जा सकता है।

सबसे अधिक "आदिम" रूप शायद case कथन है - फ़ंक्शन परिभाषाओं के लिए पैटर्न मिलान केवल एक फ़ंक्शन परिभाषा पर सिंटैक्टिक चीनी है जिसमें एक बड़ी case अभिव्यक्ति होती है।

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

ध्यान में रखना सबसे महत्वपूर्ण बात यह है कि पैटर्न मिलान बीजगणितीय डेटा प्रकार को अलग करने का एकमात्र तरीका है। बूलियन भविष्यवाणी आसानी से replaced with higher-order functions हो सकती है, लेकिन डेटा कन्स्ट्रक्टर के अंदर मूल्यों को निकालने के लिए पैटर्न मिलान की आवश्यकता होती है।

4

तीन विकल्पों में से कोई भी बिल्कुल वही काम नहीं करता है या सभी स्थितियों में इसका उपयोग किया जा सकता है।

पैटर्न मैचों की जांच करें कि किस कन्स्ट्रक्टर का उपयोग किसी दिए गए मान को बनाने के लिए किया गया था और वे चर को बाध्य करते थे। न तो अगर न ही गार्ड ऐसा करते हैं। यदि आप ईक लागू करने वाले प्रकार के एक निरंतर कन्स्ट्रक्टर (या संख्यात्मक) के खिलाफ मेल खाते हैं तो आप केवल पैटर्न मैचों के बजाय उनका उपयोग कर सकते हैं।

उदाहरण:

foo (Just x) = x+1 -- Can not do this without a pattern match (except by using 
        -- functions like fromJust that themselves use pattern matches) 
foo Nothing = 0 -- You could do this using a pattern guards like 
       -- foo x | x==Nothing = 0, but that is less readable and less 
       -- concise than using a plain pattern match 

पैटर्न गार्ड आप समानता के अलावा अन्य बातों के लिए जांच करने की अनुमति। जैसे आप जांच सकते हैं कि दिया गया नंबर शून्य से बड़ा है या नहीं। बेशक आप वही काम कर सकते हैं, लेकिन पैटर्न गार्ड आपको गार्ड के असफल होने पर अगले पैटर्न पर जाने की इजाजत देता है, जिससे उपयोग करने से कम पुनरावृत्ति हो सकती है। उदाहरण:

maybeSqrt (Just x) | x >= 0 = sqrt x 
maybeSqrt _ = Nothing 

इस इस तरह दिखेगा (कुछ भी नहीं है की पुनरावृत्ति पर ध्यान दें) होता अगर का उपयोग करना:

maybeSqrt (Just x) = if x >= 0 then sqrt x 
        else Nothing 
maybeSqrt _ = Nothing 

बिना नमूने का मिलान किया जा सकता है अन्त में यदि। यदि आप वास्तव में case x of ... पेश करने वाले किसी दिए गए मान पर पैटर्न मिलान का उपयोग नहीं करते हैं, तो आप पैटर्न गार्ड का उपयोग कर सकते हैं, थोड़ा समझ में आता है और अगर इसका उपयोग करने से कम पढ़ा जा सकता है और संक्षेप में है।

2

मैं कोड को सुंदर और पढ़ने के लिए आसान बनाता है के आधार पर चुनता हूं। जैसा कि @ डॉन इंगित करता है, इनमें से कई अलग-अलग रूपों को case पर संकलित किया गया है। उपलब्ध सिंथैक्टिक चीनी की वजह से वे अलग दिखते हैं। यह चीनी कंपाइलर के लिए नहीं है, यह मनुष्यों के लिए है। तो आप जो सोचते हैं उसके आधार पर निर्णय लें कि अन्य इंसान क्या पढ़ना चाहते हैं, और जो आपको पठनीय लगता है।

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