2010-12-26 15 views
11

मूल्यों की एक सूची को देखते हुए, मैं सूची को टी को कम करना चाहता हूं यदि सभी तत्व शून्य नहीं हैं, तो शून्य नहीं है। यह मैं एक त्रुटि देता है:आम लिस्प में बुलियन मूल्यों की सूची कैसे कम करता है?

(apply #'and (get-some-list)) 

करता है के रूप में:

[11]> (defun my-and (x y) (and x y)) 
MY-AND 

[12]> (reduce #'my-and '(T T T T T)) 
T 

[13]> (reduce #'my-and '(T T T T NIL)) 
NIL 

"# 'और" अवैध क्यों है:

(reduce #'and (get-some-list)) 

यह सबसे अच्छा मैं के साथ आ गया है ? क्या आम लिस्प में ऐसा करने के लिए एक और बेवकूफ तरीका है?

उत्तर

8

#'and अमान्य है क्योंकि and एक मैक्रो है, फ़ंक्शन नहीं।

आप एक लैम्ब्डा का उपयोग करके, एक नामित समारोह को परिभाषित करने के लिए चारों ओर प्राप्त कर सकते हैं:

(reduce (lambda (x y) (and x y)) (get-some-list) :initial-value t) 

वहाँ #' की तरह कोई शॉर्टकट हालांकि।

वैकल्पिक रूप से आप भविष्यवाणी के रूप में पहचान कार्य के साथ every का भी उपयोग कर सकते हैं।

+1

आपका उदाहरण ** गलत ** है क्योंकि 'कम करें' के पहले तर्क को शून्य या दो तर्कों के साथ बुलाया जा सकता है "(सीएल हाइपरस्पेक देखें)। इसके अलावा, आप कोई 'प्रारंभिक-मूल्य' प्रदान नहीं करते हैं। पूरी तरह से, आपका उदाहरण काम नहीं करता है जब आप रिक्त सूची या सूचियों को लंबाई 1 के साथ कम करना चाहते हैं। एक सही संस्करण है, उदाहरण के लिए, '(लैम्ब्डा (और वैकल्पिक (एक्स टी) (वाई टी)) (और xy)) ' । –

3

आप केवल सामान्य कार्यों के साथ 'तेज-उद्धरण' प्रतीक का उपयोग कर सकते हैं।

Note that only ordinary functions can be quoted with #’. It is an error to 
quote a macro function or special function this way, or to quote a symbol with 
#’ if that symbol does not name a function. 

> #’if 
Error: IF is not an ordinary function. 

COMMON LISP: A Gentle Introduction to Symbolic Computation, page 202

19

आप हर कार्य का उपयोग कर सकते हैं:

(every #'identity '(T T T T T)) -> T 

और

(every #'identity '(T T T T NIL)) -> NIL 

शायद सबसे कारगर तरीका लूप उपयोग कर रहा है:

(loop for element in '(T T T T nil) always element) -> NIL 

लाभ यह है कि सूची तत्वों पर कोई फ़ंक्शन कॉल की आवश्यकता नहीं है।

#' एक पढ़ा हुआ मैक्रो है जो अभिव्यक्ति को पढ़ने के दौरान फ़ंक्शन में फैलता है। तो #'and है (फ़ंक्शन और)।

फंक्शन यहाँ वर्णित है: http://www.lispworks.com/documentation/HyperSpec/Body/s_fn.htm

फंक्शन एक समारोह का नाम या एक लैम्ब्डा अभिव्यक्ति लेता है और इसी समारोह वस्तु देता है।

और यहाँ परिभाषित किया गया है: http://www.lispworks.com/documentation/HyperSpec/Body/m_and.htm

ऐसा नहीं है कि कहते हैं और एक मैक्रो, नहीं एक समारोह है। नतीजा यह है कि (फ़ंक्शन और) काम नहीं करता है, क्योंकि फ़ंक्शन को फ़ंक्शन की आवश्यकता होती है, न कि संबंधित फ़ंक्शन ऑब्जेक्ट को वापस करने के लिए मैक्रो। चूंकि sepp2k उसके उत्तर में वर्णन करता है, आप LAMBDA का उपयोग करके एक फ़ंक्शन बना सकते हैं और मैक्रो का उपयोग कर सकते हैं और उस फ़ंक्शन के अंदर। मैक्रोज़ को मानों के रूप में पारित नहीं किया जा सकता है और बाद में फ़नकॉल या लागू के माध्यम से बुलाया जा सकता है। यह केवल कार्यों के साथ काम करता है।

यह समाधान

(reduce (lambda (x y) (and x y)) (get-some-list)) 

रूप में लिखा है लैम्ब्डा मैक्रो (function (lambda (...) ...)) में (lambda (...) ...) फैलता है।

तो ऊपर वास्तव में है:

(reduce (function (lambda (x y) (and x y))) (get-some-list)) 

जो के रूप में

(reduce #'(lambda (x y) (and x y)) (get-some-list)) 

फंक्शन की जरूरत है क्योंकि कॉमन लिस्प मूल्यों और कार्यों के लिए नाम स्थान के बीच एक अंतर बना देता है लिखा जा सकता है। REDUCE को फ़ंक्शन को मान द्वारा तर्क के रूप में पारित करने की आवश्यकता है। तो हमें फ़ंक्शन नेमस्पेस से फ़ंक्शन पुनर्प्राप्त करने की आवश्यकता है - जो फ़ंक्शन का उद्देश्य है। जब भी हम फ़ंक्शन ऑब्जेक्ट को पास करना चाहते हैं, तो हमें इसे फ़ंक्शन नेमस्पेस से प्राप्त करने की आवश्यकता होती है।

एक स्थानीय समारोह के मामले में उदाहरण के लिए:

(flet ((my-and (x y) (and x y))) 
    #'my-and) 

लैम्ब्डा एक सुविधा मैक्रो में विस्तारित रूप में (समारोह (लैम्ब्डा ...)) कॉमन लिस्प के डिजाइन के दौरान जोड़ा गया है।