2010-08-11 12 views
5

मैं किसी अन्य विधि में उपयोग के लिए फ़ंक्शन का नाम पास कर रहा हूं।क्लोजर में मूल्यांकन के लिए विधि नाम पास करने के लिए बेवकूफ तरीका?

(defn mapper [m function] 
    (cond 
    (= '() m) '() 
    true (cons (function (first m)) 
      (mapper (rest m) function)))) 

(println (mapper '((blue red)(green red)(white red)) #'first)) 

क्या क्लोजर में ऐसा करने का एक और बेवकूफ तरीका है?

+2

मुझे लगता है कि उपयोग करने के लिए [नक्शा] (http://clojure.github.com/clojure/clojure.core-api है यह करने के लिए _most_ मुहावरेदार रास्ता .html # clojure.core/map) फ़ंक्शन: '(नक्शा पहले '((नीला लाल) (हरा लाल) (सफेद लाल)))'। – Jonas

उत्तर

8
  • सूचियों को सूचियों को पसंद करें। आपको अधिकतर समय में वेक्टर उद्धृत करने की आवश्यकता नहीं है, और इसमें कई चीजों के लिए बेहतर प्रदर्शन है, जैसे यादृच्छिक पहुंच। अन्य लिस्पस की तुलना में क्लोजर में सूचियों का उपयोग शायद ही कभी किया जाता है।
  • उद्धृत प्रतीकों के लिए कीवर्ड पसंद करें। कीवर्ड "निरंतर तार" या समेकित मान के रूप में खड़े होते हैं। क्लोजर में कीवर्ड नामस्थान से संबंधित हो सकते हैं, इसलिए उनके पास प्रतीकों के सभी फायदे हैं। और फिर, कीवर्ड उद्धृत करने की कोई आवश्यकता नहीं है, जो अच्छा है। क्लोजर में उद्धृत प्रतीकों का उपयोग शायद ही कभी किया जाता है, जब तक आप मैक्रोज़ लिख रहे हों।
  • #'first "पहला" नामक var है; first "पहले" नामक var का मान है, यानी एफएन। इस मामले में (#'first foo) और (first foo) समान उत्तर देते हैं, लेकिन #'first हर बार जब आप इसे कॉल करते हैं तो अतिरिक्त बहिष्कार करता है। तो ऐसा तब तक न करें जब तक कि आप उस धारणा को खत्म नहीं करना चाहते हैं। आमतौर पर #' का उपयोग करने की आवश्यकता नहीं है।
  • अंतर्निहित map आलसी है, जबकि आपका नहीं है। अंतर्निहित map बेहतर प्रदर्शन के लिए खंडित seqs का लाभ लेता है, जबकि आपका नहीं है।बेवकूफ कोड आलसी होना या चंकित seqs का उपयोग नहीं है, लेकिन ध्यान रखें कि बिल्टिन में इस जादू का कुछ चल रहा है। तो लाभ लेने के लिए अच्छा है।
  • (= '() x) की बजाय, खाली सीक के लिए idiomatic परीक्षण (seq x) है, जो nil देता है यदि x खाली है। ध्यान दें कि क्लोजर में, (= '() nil) गलत है।
  • यदि आपको खाली सूची (जिसे आपको शायद ही कभी करने की ज़रूरत है) का उपयोग करने की आवश्यकता है, तो आपको इसे उद्धृत करने की आवश्यकता नहीं है। बस () का उपयोग करें।
  • निर्मित map फ़ंक्शन तर्क पहले लेता है क्योंकि यह एकाधिक संग्रह तर्क स्वीकार करता है। जब कोई फ़ंक्शन एकाधिक तर्क लेता है, तो उन तर्कों को तर्क सूची में अंतिम रूप से जाना होता है। मुझे लगता है कि यह अन्य तरीके से भी बेहतर पढ़ता है: "(नक्शा एफ कॉल): इस संग्रह को इस संग्रह में मानचित्र करें"।
  • यदि आपके पास केवल दो विकल्प हैं तो cond का उपयोग करने की आवश्यकता नहीं है। आप इसके बजाय if का उपयोग कर सकते हैं। और यदि आपके if में से एक शाखा nil लौटाती है, तो आप when का उपयोग कर सकते हैं। उपयुक्त होने पर when और if का उपयोग करना अच्छा होता है, क्योंकि वे आपके इरादे को तुरंत पाठक को सिग्नल करते हैं, जबकि cond कुछ भी कर सकता है और पाठक को और पढ़ने के लिए मजबूर करता है।

राफल डॉउगर्ड का संस्करण मूर्खतापूर्ण है, सिवाय इसके कि मैं चारों ओर तर्कों के आदेश को फ़्लिप करता हूं। और मैं इसे इस तरह फोन चाहते हैं:

user> (mapper first [[:blue :red] [:green :red] [:white :red]]) 
(:blue :green :white) 
+0

तर्कों को फ़्लिप करने के बारे में सहमति हुई। या तो वह या '(डिस्पन मैपर [coll f & args] ...)' 'args' के साथ f के अतिरिक्त तर्क के रूप में पारित किया गया है ताकि' (मैपर [5 2 3] + 1) जैसी चीजें संभव हों। –

+0

सुझावों का महान संग्रह। – edbond

4

मेरा मानना ​​है कि आपको यह अधिकतर मूर्खतापूर्ण मिला है। Clojure खुद के map उपयोग करता है:

(defn mapper [coll f] 
(when-let [s (seq coll)] 
    (cons (f (first s)) (mapper (rest s) f)))) 

मैं इसे गंभीर रूप से छोटा है - मूल एक आलसी अनुक्रम पैदा करता है, कई संग्रह, chunked-seqs, आदि वैसे के साथ सौदों - मुझे लगता है आप वास्तविक समारोह पास करना चाहते हैं, यह नाम है।

coll और f क्रमशः संग्रह और कार्यों का प्रतिनिधित्व करने के लिए मूर्खतापूर्ण तर्क नाम हैं।

4

आपका संस्करण मेरे लिए अच्छा लग रहा है। क्लोजर कोड बेस में आपके द्वारा देखे जाने वाले सामान्य नाम संग्रह के लिए 'coll' है। मैंने 'एक्सएस' भी देखा है जो हास्केल शैली है, मुझे लगता है। आप विभिन्न सम्मेलनों पर Clojure library coding standards का भी उल्लेख कर सकते हैं।

उदाहरण पर वापस आ रहा है: दो अवलोकन।

  1. उपयोग करें: अन्य सामान्य लिस्प शैली 'टी' के बजाय, 'कंड' से बचने की स्थिति के रूप में उपयोग करें।
  2. सूचियों को मानने के बजाय, अनुक्रमों को सोचें।
मन में इन दोनों के साथ

, अगर मैं अपने कोड को फिर से लिखने:

user> (defn mapper [coll f] 
     (cond 
      (not (seq coll)) nil 
      :else (conj (mapper (next coll) f) 
         (f (first coll))))) 
#'user/mapper 
user> (mapper '(1 2 3) #(* % %)) 
(1 4 9) 
user> (mapper [1 2 3] #(* % %)) 
(1 4 9) 

ध्यान दें कि संयोजक "सही काम" करता है जहाँ तक संग्रह में चिंतित हैं। यह एक वेक्टर की पूंछ के लिए, सूची के सिर में नया तत्व जोड़ता है और इसी तरह। पारंपरिक लिस्प में पहले/आराम मुहावरे के बजाय 'अगली' के उपयोग को भी ध्यान दें। 'अगला' पहले तत्व के बाद तत्वों का अनुक्रम देता है। इसलिए, संग्रह पर seq'ing द्वारा खाली-जास की जांच की जा सकती है जो खाली सूची या खाली वेक्टर के लिए शून्य वापस आ जाएगी। इस तरह यह सभी संग्रहों के लिए काम करता है।

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