2011-10-17 12 views
5

के संबंध में चलो एक फ़ंक्शन को परिभाषित करता है, जिसमें दो पैरामीटर होते हैं - मानचित्र और एक कुंजी। कुंजी नक्शा पैरामीटर अपघटनdefn vs। Decomposition

(defn myfunc [{v k} k] 
    v) 

से संदर्भित है जब मैं फोन:

(myfunc {:a 10} :a) 

यह आश्चर्य की बात की उम्मीद उत्पादन परिणाम: 10

दें में इसी प्रकार के बात:

(let [{v k} {:a 10} k :a] v) 

विफल रहता है, क्योंकि के पर परिभाषित नहीं किया गया है पल, जब पहले भाग का मूल्यांकन किया जाता है।

मेरा प्रश्न है: में अपघटन की तुलना में फ़ंक्शन पैरामीटर के अंदर अपघटन अलग-अलग व्यवहार क्यों करते हैं अभिव्यक्तियों को छोड़ दें?

उत्तर

3

defn प्रपत्र मैं इस के बराबर मिलता है (हटाया .withMeta सामान और पुन: स्वरूपित) Macroexpanding:

(def myfunc 
    (fn* myfunc 
     ([p__11393 k] 
      (let* [map__11394 p__11393 
       map__11394 (if (seq? map__11394) 
           (apply hash-map map__11394) 
           map__11394) 
       v   (get map__11394 k)] 
       v)))) 

तो यहाँ हम देख सकते हैं कि {v k} नक्शा पहले एक स्थानीय चर p__11393 करने के लिए सौंपा वास्तव में है। फिर if कथन परीक्षण यदि वह चर वास्तव में एक अनुक्रम है और इसे हैश-मैप में बदल देता है, तो अन्यथा इसे छोड़ दें। महत्वपूर्ण बात यह है कि k को सौंपा गया मान के बाद मानचित्र में देखा गया है, यह सब होता है, इस प्रकार यह त्रुटि के बिना काम करता है (और यदि :a मानचित्र में नहीं था, तो get उस मामले में nil देता है)।

दूसरी ओर macroexpanding let प्रपत्र पर मैं

(let* 
    [map__11431 
    {:a 10} 
    map__11431 
    (if (seq? map__11431) (apply hash-map map__11431) map__11431) 
    v 
    (get map__11431 k) 
    k 
    :a] 
    v) 

हो और यहाँ हम देख सकते हैं कि v(get map__11431 k) का परिणाम हो जाता है, लेकिन k इस बिंदु पर अभी तक परिभाषित नहीं है, इसलिए त्रुटि।

+0

अब सवाल है, एक बग के रूप में या एक सुविधा के रूप में विचार किया जाना है, तो इस तरह के अंतर गई है ... – aav

+0

मैं कहूंगा अगर कोई जानता है कि कार्य के शरीर के अंदर विनाश होता है तो यह आश्चर्यजनक नहीं है, इसलिए एक बग नहीं है। लेकिन मुझे लगता है कि इस तथ्य को उचित स्थानों में बेहतर समझाया जाना चाहिए - अगर मुझे सही ढंग से क्लोजर की खुशी याद है, उदाहरण के लिए, वास्तव में इसमें शामिल नहीं होता है। – Paul

+0

दिलचस्प क्या है (लेकिन आश्चर्य की बात नहीं है) कि उसकी इच्छा काम नहीं करेगी: (deff myfunc [{v k} {k: k1}] v) – aav

0

यह एक पूरा जवाब नहीं है, लेकिन निम्नलिखित काम करता है:

user=> (defn myfunc [{v k} k] v) 
#'user/myfunc 
user=> (myfunc {:a 10} :a) 
10 
user=> (let [k :a {v k} {:a 10}] v) 
10 
user=> 
+0

यह निश्चित रूप से काम करेगा, क्योंकि * के * किसी अन्य चीज़ से पहले परिभाषित किया गया है – aav