2012-05-21 14 views
8

मैं कभी कभी कार्यों की कम arity संस्करणों, कि एक आंशिक समारोह लौटने के लिए, उदाहरण के लिए परिभाषित करने के लिए यह Clojure में सुविधाजनक मिल गया हैपरिभाषित कम arity आंशिक कार्यों

(defn prefix 
    ([pre string] 
    (str pre ":" string)) 

    ([pre] 
    (fn [string] 
     (prefix pre string)))) 

इसका मतलब है कि आप कर सकते हैं या तो:

(prefix "foo" 78979) 
=> "foo:78979" 

((prefix "foo") 78979) 
=> "foo:78979" 

यह काफी हास्केल-ish लगता है और partial आंशिक कार्यों बनाने की ज़रूरत नहीं बचा जाता है।

लेकिन यह लिस्प में अच्छा कोडन शैली/एपीआई डिजाइन माना जाता है?

+0

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

+0

मुझे लगता है कि यह अभी भी विचारशील है यदि आप उन्हें पठनीयता के लिए आंशिक रूप से नामित करते हैं जब आप उन्हें परिभाषित करते हैं: (def prefix (आंशिक ...)) तो इसमें दोनों हैं: संदर्भ का नाम और यह स्पष्ट है।ध्यान दें कि आप अब defn का उपयोग नहीं करते लेकिन def- आंशिक आप के लिए समारोह पैदा कर रही है – KIMA

उत्तर

7

भाषाओं जहां कार्यों डिफ़ॉल्ट रूप से curried कर रहे हैं, कार्यप्रणाली कॉल भी curried कर रहे हैं। जब कोई (f a b c) लिखता है, तो भाषा इसे (((f a) b) c) के रूप में व्याख्या करती है। क्लोजर में यह मामला नहीं है।

मुझे विश्वास है कि ऐसा माहौल कॉल डिफ़ॉल्ट रूप से curried नहीं कर रहे हैं में curried कार्यों बनाने एक वैचारिक बेमेल बनाता है - (। मैं अपने कोड के मानव पाठकों मतलब) इस संरचना शायद पाठकों में भ्रम की स्थिति पैदा होगी

अपने कार्य हैं 2 से अधिक तर्क हैं, परिभाषा बदसूरत हो जाती है। मान लीजिए कि एक समारोह में 4 तर्क हैं। करीनी कॉल को पूरी तरह से अनुकरण करने के लिए, आपको ((f a b) c d) जैसे मामलों को संभालने की आवश्यकता है जब कोई व्यक्ति पहले 2 तर्क और फिर शेष दो पास करता है। इस मामले में दो-तर्क फ़ंक्शन के अधिभारित संस्करण को एक अधिभारित फ़ंक्शन वापस करने की आवश्यकता होती है जो इस पर निर्भर करता है कि यह 1 या 2 तर्क प्राप्त करता है या नहीं। मुझे लगता है कि मैक्रोज़ के साथ स्वचालित करना संभव है, लेकिन फिर भी।

इसके अलावा, आप डिफ़ॉल्ट तर्कों और & rest निर्माण को परिभाषित करने की संभावना मार डालते हैं।

+0

डिफ़ॉल्ट तर्कों और variadic 'और rest' कार्यों – 6502

+0

@ 6502 हां। पूर्णता के लिए संपादित किया गया। –

6

हममम ... व्यक्तिगत रूप से, मैं नहीं बल्कि partial, देखने के बाद से है कि यह स्पष्ट करता है क्या हो रहा है चाहता हूँ।

मैं इसे "अच्छा" या "बुरा" शैली कोडिंग है अगर पता नहीं है, लेकिन मैं कभी नहीं मौजूदा Clojure कोड में से पहले इस शैली को देखा है और मैं कल्पना कर सकते हैं कि एक एपीआई का उपयोग कर लोगों को दोनों (prefix "foo" 78979) और (prefix "foo") की उम्मीद करेंगे उसी तरह की वस्तु वापस करें।

फर्क करने के लिए के बीच दोनों कार्यों को स्पष्ट आप इस के बजाय की तरह कुछ कर सकता है:

(defn prefix [pre string] 
    (str pre ":" string)) 

(defn prefix-fn [pre] 
    (fn [string] 
    (prefix pre string))) 

(prefix "foo" 78979)  ; => "foo:78979" 
((prefix-fn "foo") 78979) ; => "foo:78979" 
+2

"मैं कभी नहीं इस शैली से पहले मौजूदा Clojure कोड में देखा है" --- यह सब हिक्की के नए पुस्तकालय reducers खत्म हो गया। –

+0

आप सही हैं, इसे इंगित करने के लिए धन्यवाद। – Gert

9

एक curried समारोह बनाने के लिए partial का उपयोग स्पष्ट की अवधारणा पर आधारित है बेहतर है (ज्यादातर मामलों में:))। और मैंने पाया है कि इस अवधारणा को गतिशील रूप से टाइप की गई भाषाओं जैसे क्लोजर, पायथन आदि में अधिक लागू/उपयोग किया जा सकता है, गायब प्रकार के हस्ताक्षर/स्थैतिक-टाइपिंग के कारण यह चीजों को स्पष्ट करने के लिए और अधिक समझ में आता है।

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