clojure क्लोजर में उच्च-क्रम के कार्य




currying higher-order-functions (3)

मैंने अमलॉय द्वारा सुझाए गए कार्यों के साथ थोड़ा खेला है। मुझे करी पर तर्क करने की संख्या का स्पष्ट विनिर्देश पसंद नहीं है। इसलिए मैंने अपना कस्टम मैक्रो बनाया है। यह एक उच्च क्रम फ़ंक्शन को निर्दिष्ट करने का पुराना तरीका है:

(defn-decorated old-sum
  [(curry* 3)]
  [a b c]
  (+ a b c))

यह मेरा नया मैक्रो है:

(defmacro defn-ho
  [fn-name & defn-stuff]
  (let [number-of-args (count (first defn-stuff))]
    `(defn-decorated ~fn-name [(curry* ~number-of-args)] [email protected]defn-stuff)))

और यह नया निहित तरीका है:

(defn-ho new-sum [a b c] (+ a b c))

जैसा कि आप देख सकते हैं कि (करी) और अन्य सामान का कोई निशान नहीं है, बस पहले की तरह अपने घुमावदार फ़ंक्शन को परिभाषित करें।

दोस्तों, आपको क्या लगता है? विचार? सुझाव? अलविदा!

Alfedo

संपादित करें: मैंने docstring के बारे में amalloy मुद्दे के अनुसार मैक्रो को संशोधित किया है। यह अद्यतन संस्करण है:

(defmacro defhigh
  "Like the original defn-decorated, but the number of argument to curry on
  is implicit."
  [fn-name & defn-stuff]
  (let [[fst snd] (take 2 defn-stuff)
         num-of-args (if (string? fst) (count snd) (count fst))]
    `(defn-decorated ~fn-name [(curry* ~num-of-args)] [email protected]defn-stuff)))

मैं दूसरे बंधन के अंदर के कथन को पसंद नहीं करता। इसे और अधिक रसीद बनाने के बारे में कोई विचार?

क्लोजर कमाल का है, हम सभी यह जानते हैं, लेकिन यह बात नहीं है। मैं सोच रहा हूँ कि हास्केल की तरह उच्च-क्रम के कार्यों को बनाने और प्रबंधित करने का मुहावरेदार तरीका क्या है। क्लोजर में मैं निम्नलिखित कर सकता हूं:

(defn sum [a b] (+ a b))

लेकिन (sum 1) एक फ़ंक्शन वापस नहीं करता है: यह एक त्रुटि का कारण बनता है। बेशक, आप ऐसा कुछ कर सकते हैं:

(defn sum
  ([a] (partial + a)) 
  ([a b] (+ a b)))

इस मामले में:

user=> (sum 1)
#<core$partial$fn__3678 [email protected]>
user=> ((sum 1) 2)
3

लेकिन यह आगे बढ़ने का सही तरीका नहीं है। कोई विचार?
मैं sum समारोह को लागू करने के बारे में बात नहीं कर रहा हूं, मैं उच्च स्तर के अमूर्त स्तर पर बात कर रहा हूं। क्या कोई मुहावरेदार पैटर्न का पालन करना है? कुछ मैक्रो? क्या मैक्रो को परिभाषित करने का सबसे अच्छा तरीका है या वैकल्पिक समाधान हैं?


यह आपको वही करने देगा जो आप चाहते हैं:

(defn curry
  ([f len] (curry f len []))
  ([f len applied]
    (fn [& more]
      (let [args (concat applied (if (= 0 (count more)) [nil] more))]
        (if (< (count args) len)
          (curry f len args)
          (apply f args))))))

इसका उपयोग कैसे करें:

(def add (curry + 2)) ; read: curry plus to 2 positions
((add 10) 1) ; => 11

[nil] साथ सशर्त यह सुनिश्चित करने के लिए है कि प्रत्येक एप्लिकेशन क्यूरेड अवस्था में कुछ आगे की प्रगति सुनिश्चित करता है। इसके पीछे एक लंबी व्याख्या है लेकिन मैंने इसे उपयोगी पाया है। यदि आप इस बिट को पसंद नहीं करते हैं, तो आप args को इस प्रकार सेट कर सकते हैं:

[args (concat applied more)]

जावास्क्रिप्ट के विपरीत, हमारे पास उत्तीर्ण फ़ंक्शन की विविधता को जानने का कोई तरीका नहीं है और इसलिए आपको उस लंबाई को निर्दिष्ट करना होगा जो आप उम्मीद करते हैं। यह क्लोजुर [लिपि] में बहुत मायने रखता है, जहां एक फ़ंक्शन में कई आकृतियाँ हो सकती हैं।


क्लोजर समूह पर किसी ने पहले ही इसे लागू कर दिया है। आप यह निर्दिष्ट कर सकते हैं कि किसी फ़ंक्शन में कितने आरजीबी हैं, और यह आपके लिए खुद को करी देगा जब तक कि यह बहुत सारे नहीं हो जाता।

क्लोजर में डिफ़ॉल्ट रूप से ऐसा नहीं होने का कारण यह है कि हम वैरिएबल फ़ंक्शंस को ऑटो-क्यूरेड फ़ंक्शंस में पसंद करते हैं, मुझे लगता है।





higher-order-functions