यहां मुद्दा सूक्ष्म और संभावित रूप से मैक्रोज़ के बारे में कुछ समझने के बिना ग्रोक करना मुश्किल है।
मैक्रोज़ सिंटैक्स में उसी तरह से हेरफेर करते हैं जो कार्य मूल्यों में हेरफेर करता है। वास्तव में, मैक्रोज़ सिर्फ एक हुक के साथ काम करते हैं जो उन्हें संकलन समय पर मूल्यांकन करने का कारण बनता है। वे डेटा शाब्दिक पारित होते हैं जिन्हें आप स्रोत कोड में देखते हैं और मूल्यांकन शीर्ष-डाउन होते हैं। के एक समारोह और एक मैक्रो एक ही शरीर है कि बनाने ताकि आप अंतर देख सकते हैं करते हैं:
(defmacro print-args-m [& args]
(print "Your args:")
(prn args))
(defn print-args-f [& args]
(print "Your args:")
(prn args))
(print-args-m (+ 1 2) (str "hello" " sir!"))
; Your args: ((+ 1 2) (str "hello" " sir!"))
(print-args-f (+ 1 2) (str "hello" " sir!"))
; Your args: (3 "hello sir!")
मैक्रो उनकी वापसी मान से बदल रहे हैं। आप macroexpand
(defmacro defmap [sym & args]
`(def ~sym (hash-map [email protected]))) ; I won't explain these crazy symbols here.
; There are plenty of good tutorials around
(macroexpand
'(defmap people
"Steve" {:age 53, :gender :male}
"Agnes" {:age 7, :gender :female}))
; (def people
; (clojure.core/hash-map
; "Steve" {:age 53, :gender :male}
; "Agnes" {:age 7, :gender :female}))
इस बिंदु पर के साथ इस प्रक्रिया का निरीक्षण कर सकते हैं, मैं शायद व्याख्या करनी चाहिए कि '
निम्न प्रपत्र का कारण बनता है होना करने के लिए quote
डी। इसका मतलब है कि संकलक फॉर्म को पढ़ेगा, लेकिन इसे निष्पादित नहीं करेगा या प्रतीकों को हल करने का प्रयास करेगा और आगे भी। यानी 'conj
एक प्रतीक का मूल्यांकन करता है, जबकि conj
किसी फ़ंक्शन का मूल्यांकन करता है। (eval 'conj)
(eval (quote conj))
के समतुल्य conj
के बराबर है।
इस बात को ध्यान में रखते हुए, पता है कि आप नामस्थान के रूप में प्रतीक को हल नहीं कर सकते हैं जब तक कि इसे किसी भी तरह से आपके नामस्थान में जादुई रूप से आयात नहीं किया जाता है। यह require
फ़ंक्शन करता है। यह प्रतीक लेता है और वे नामस्थानों को मेल खाता है, जो उन्हें वर्तमान नामस्थान में उपलब्ध कराते हैं।
(macroexpand
'(ns sample.core
(:require clojure.set clojure.string)))
; (do
; (clojure.core/in-ns 'sample.core)
; (clojure.core/with-loading-context
; (clojure.core/refer 'clojure.core)
; (clojure.core/require 'clojure.set 'clojure.string)))
देखें कि यह कैसे प्रतीकों clojure.set
और हमारे लिए clojure.string
उद्धृत किया:
देखते हैं क्या ns
मैक्रो के लिए विस्तारित करते हैं? कितना सुविधाजनक! लेकिन :require
के चरण में require
का उपयोग करते समय क्या सौदा है?
(macroexpand
'(ns sample.core
(require clojure.set clojure.string)))
; (do
; (clojure.core/in-ns 'sample.core)
; (clojure.core/with-loading-context
; (clojure.core/refer 'clojure.core)
; (clojure.core/require 'clojure.set 'clojure.string)))
ऐसा लगता है कि जो कोई भी ns
मैक्रो लिखा था, काफी अच्छा हमें यह दोनों तरीकों से करते हैं के लिए गया था के बाद से इस परिणाम वास्तव में पहले की तरह ही है। Neato!
संपादित करें: tvachon केवल :require
का उपयोग कर के बाद से यह केवल आधिकारिक तौर पर समर्थित प्रपत्र
है लेकिन क्या ब्रैकेट के साथ सौदा है के बारे में सही है?
(macroexpand
'(ns sample.core
(:require [clojure.set]
[clojure.string])))
; (do
; (clojure.core/in-ns 'sample.core)
; (clojure.core/with-loading-context
; (clojure.core/refer 'clojure.core)
; (clojure.core/require '[clojure.set] '[clojure.string])))
बाहर कर देता है वे भी उद्धृत किया जाए, ठीक जैसे हम अगर हम require
को स्टैंडअलोन कॉल लिख रहे थे करना चाहते हैं।
यह भी पता चला है कि ns
परवाह नहीं है कि हम इसे सूची (माता-पिता) या वैक्टर (ब्रैकेट) के साथ काम करने के लिए देते हैं या नहीं। यह तर्कों को चीजों के अनुक्रम के रूप में देखता है। उदाहरण के लिए, इस काम करता है:
(ns sample.core
[:gen-class]
[:require [clojure.set]
[clojure.string]])
require
, के रूप में टिप्पणी में amalloy से कहा, वैक्टर और सूचियों के लिए अलग अलग अर्थ विज्ञान है, तो उन अप मिश्रण नहीं है!
अंत में, निम्नलिखित कार्य क्यों नहीं करते?
(ns sample.core
(:require 'clojure.string 'clojure.test))
खैर, ns
के बाद से है हमारे हमारे लिए के हवाले से, इन प्रतीकों दो बार उद्धृत करने के लिए, जो केवल एक बार उद्धृत किया जा रहा से शब्दार्थ अलग है और यह भी शुद्ध पागलपन है।
conj ; => #<core$conj [email protected]>
'conj ; => conj
''conj ; => (quote conj)
'''conj ; => (quote (quote conj))
मुझे उम्मीद है कि यह मदद करता है, और मैं निश्चित रूप से मैक्रोज़ लिखने के तरीके सीखने की सलाह देता हूं। वे बहुत मजेदार हैं।
संभावित डुप्लिकेट [एनएस फॉर्म में आवश्यकता क्यों आवश्यक फ़ंक्शन से अलग व्यवहार करती है] (http://stackoverflow.com/questions/3719929/why-does-require-in-the-ns-form-behave- अलग-अलग-आवश्यकता-फ़ंक्शन) –
एचएम, वास्तव में [] और प्रतिकृति और clj कोड के बीच अंतर के बारे में नहीं पूछता है। –