2012-11-03 50 views
76

कुछ मैं कम अंकन # (..)बेनामी समारोह आशुलिपि

निम्नलिखित कार्यों का उपयोग गुमनाम कार्यों के बारे में समझ में नहीं आता है:

REPL> ((fn [s] s) "Eh") 
"Eh" 

लेकिन यह नहीं करता है:

REPL> (#(%) "Eh") 

यह काम करता है:

REPL> (#(str %) "Eh") 
"Eh" 

मुझे समझ में नहीं आता है कि क्यों (# (%) "एएच") काम नहीं करता है और साथ ही मुझे str((एफएन [एस] एस) में उपयोग करने की आवश्यकता नहीं है " एएच ")

वे दोनों अज्ञात कार्य हैं और वे दोनों एक पैरामीटर लेते हैं। शॉर्टंड नोटेशन को फ़ंक्शन की आवश्यकता क्यों होती है जबकि अन्य नोटेशन नहीं होता है?

उत्तर

115
#(...) 

के लिए

(fn [arg1 arg2 ...] (...)) 

(जहां argN की संख्या कितने% N आप शरीर में है पर निर्भर करता है) आशुलिपि है। तो जब आप लिखें:

#(%) 

इसे करने के लिए अनुवाद है:

(fn [arg1] arg1) 

आपका संस्करण रिटर्न के रूप में ARG1:

(fn [arg1] (arg1)) 

सूचना है कि यह आपका पहला गुमनाम समारोह है, जो की तरह है से अलग है एक मान, जो संस्करण शॉर्टैंड का विस्तार करने से आता है उसे एक फ़ंक्शन के रूप में कॉल करने का प्रयास करता है। आपको एक त्रुटि मिलती है क्योंकि एक स्ट्रिंग मान्य फ़ंक्शन नहीं है।

चूंकि शॉर्टेंड शरीर के चारों ओर कोष्ठक का एक सेट प्रदान करता है, इसका उपयोग केवल एक फ़ंक्शन कॉल या विशेष फ़ॉर्म निष्पादित करने के लिए किया जा सकता है।

18

जब आप #(...) उपयोग करते हैं, जैसा कि आप कल्पना कर सकते हैं बजाय लिख रहे हैं (fn [args] (...)), कोष्ठकों आप सही पाउंड के बाद शुरू कर दिया शामिल है।

((fn [s] (s)) "Eh") 

क्योंकि आप कॉल स्ट्रिंग "एह" की कोशिश कर रहे हैं जो स्पष्ट रूप से काम नहीं करता है:

तो, अपने गैर काम उदाहरण के लिए बदल देता है। str के साथ आपका उदाहरण काम करता है क्योंकि अब आपका कार्य (s) के बजाय (str s) है। (identity s) आपके पहले उदाहरण के करीब एनालॉग होगा, क्योंकि यह स्ट्र को सहारा नहीं देगा।

यह भावना यदि आप इसके बारे में सोचते बनाता है, यह पूरी तरह से कम से कम उदाहरण के अलावा अन्य के बाद से प्रत्येक गुमनाम समारोह कुछ कॉल करने के लिए जा रहा है, तो यह वास्तव में बनाने के लिए कोष्ठक का एक और नेस्टेड सेट की आवश्यकता के लिए एक छोटे से मूर्ख होगा एक कॉल।

56

जैसा कि अन्य उत्तरों पहले से ही बहुत अच्छी तरह से इंगित किए गए हैं, #(%) आपने वास्तव में (fn [arg1] (arg1)) जैसे कुछ विस्तार किया है, जो (fn [arg1] arg1) जैसा नहीं है।

@ जॉन उदासी ने कहा कि तुम सिर्फ identity उपयोग कर सकते हैं, लेकिन आप एक तरह से #(...) प्रेषण मैक्रो का उपयोग identity लिखने के लिए देख रहे हैं, तो आप इसे इस तरह कर सकते हैं:

#(-> %) 

के संयोजन से #(...)-> threading macro के साथ मैक्रो प्रेषण (fn [arg1] (-> arg1)) जैसे कुछ में विस्तारित हो जाता है, जो कि (fn [arg1] arg1) तक फैलता है, जो सिर्फ वांछित है। मुझे -> और #(...) मैक्रो कॉम्बो वेक्टर लौटने वाले साधारण कार्यों को लिखने के लिए सहायक भी हैं, उदाहरण:

#(-> [%2 %1])