2014-11-03 4 views
5

हम एक चर को कोई मान निर्दिष्ट हैं:कैद मूल्य

(setf i 10) 

और फिर एक इस पर एक लैम्ब्डा समारोह समापन बनाएँ:

(setf f #'(lambda() i)) 

हम व्यवहार

(incf i) ;=> 11 
(funcall f) ;=> 11 

इसके बजाय, मैं फ़ंक्शन वा को उस समय i के मान को हमेशा वापस करना चाहता हूं एस बनाया गया है। उदा .:

(incf i) ;=> 11 
(funcall f) ;=> 10 

अनिवार्य रूप से मैं लैम्ब्डा शरीर के अंदर एक शाब्दिक में i चालू करने के लिए करना चाहते हैं। क्या आम लिस्प में ऐसा करना संभव है? इसका कारण यह है कि मैं एक लूप के अंदर एक से अधिक लैम्ब्डा बना रहा हूं, और उनके शरीर में इंडेक्स का उपयोग करने की आवश्यकता है, बिना सृजन के अलग-अलग।

+3

मैं Dolist, उदाहरण के लिए निम्न में से किसी के साथ परिभाषित किया जा सकता है 'एलईटी' के बारे में कुछ पढ़ने का प्रस्ताव है। –

उत्तर

8

बस मूल्य की प्रति के साथ एक चर को बांधें। उदाहरण के लिए:

(let ((i i)) 
    (lambda() i)) 

यह वास्तव में, यात्रा निर्माणों के साथ एक महत्वपूर्ण तकनीक है क्योंकि कुछ

तरह
(loop for i from 1 to 10 
    collecting (lambda() i)) 

एक ही चर से अधिक दस बंदी वापस आ सकते हैं, तो यह लिखने के लिए आवश्यक हो जाता है:

(loop for i from 1 to 10 
    collecting (let ((i i)) (lambda() i))) 

यदि आपको वास्तव में केवल एक फ़ंक्शन की आवश्यकता है जो मान देता है, तो आप constantly का भी उपयोग कर सकते हैं (लेकिन मुझे उम्मीद है कि असली उपयोग केस अधिक जटिल है):

(loop for i from 1 to 10 
    collecting (constantly i)) 

कुछ मामलों में पुनरावृत्ति रूपों में अस्पष्टता वास्तव में मानक द्वारा निर्दिष्ट की जाती है। जैसे, dotimes के लिए, dolist

यह कार्यान्वयन पर निर्भर है dotimes प्रत्येक यात्रा पर वार करने का एक नया बंधन स्थापित करता है कि क्या है या यह है कि क्या शुरुआत में वर के लिए एक बाध्यकारी एक बार स्थापित करता है और फिर बाद में किसी भी पुनरावृत्तियों पर यह प्रदान करती है।

अधिक आदिम do, हालांकि, वास्तव में फार्म के लिए बाइंडिंग का एक सेट है कि वहाँ है, और है कि वे एक यात्रा पर अपडेट किया जाता है (जोर जोड़ा) निर्दिष्ट करता है:

प्रत्येक की शुरुआत में पहले के अलावा पुनरावृत्ति, वर्र्स निम्नानुसार अपडेट किए गए हैं।& Hellip;

यह अस्पष्टता कार्यान्वयन को थोड़ा अधिक लचीलापन देती है।

(defmacro dolist ((var list &optional result) &body body) 
    `(progn (mapcar #'(lambda (,var) 
         ,@(ex:body-declarations body) 
         (tagbody 
         ,@(ex:body-tags-and-statements body))) 
        ,list) 
      (let ((,var nil)) 
      ,result))) 

(defmacro dolist ((var list &optional result) &body body) 
    (let ((l (gensym (string '#:list-)))) 
    `(do* ((,l ,list (rest ,l)) 
      (,var (first ,l) (first ,l))) 
      ((endp ,l) ,result) 
     ,@body))) 
+0

हल हो गया! मैं आपके दूसरे उदाहरण में पुनरावृत्ति निर्माण कर रहा था, और अंतिम सूचकांक के मूल्य के साथ सभी बंद हो रहा था। धन्यवाद यहोशू! –

+0

@DiogoFranco हाँ, कुछ जानबूझकर अस्पष्टता (कार्यान्वयन-निर्भर व्यवहार) है कि कुछ पुनरावृत्तियों में कितने बाध्यकारी रूप हैं। मैंने अपने उत्तर में कुछ और क्यों जोड़ा है, यह बताने के लिए क्यों। –

4

यह बिल्कुल स्पष्ट नहीं है कि आप यहां क्या चाहते हैं। यदि आप एक स्कोप बनाना चाहते हैं जिसमें एक साझा चर i मौजूद है, तो आप इसे let के साथ कर सकते हैं।

CL-USER> (let ((i 10)) 
     (defun show-i() i) 
     (defun inc-i() (incf i)) 
     (defun dec-i() (decf i))) 
DEC-I 
CL-USER> (show-i) 
10 
CL-USER> (inc-i) 
11 
CL-USER> (show-i) 
11 
CL-USER> (dec-i) 
10 
CL-USER> (dec-i) 
9 
CL-USER> (show-i) 
9 
CL-USER> 

आप गतिशील scoped चर का उपयोग करने के लिए देख रहे हैं, तो आप सीधे-अप defvar उपयोग कर सकते हैं।

CL-USER> (defvar *a* 10) 
*A* 
CL-USER> (defun show-a() *a*) 
SHOW-A 
CL-USER> (show-a) 
10 
CL-USER> *a* 
10 
CL-USER> (incf *a*) 
11 
CL-USER> (incf *a*) 
12 
CL-USER> (show-a) 
12 
CL-USER> 
+0

ओह, लेकिन मुझे बिल्कुल विपरीत चाहिए। उपर्युक्त मेरे उदाहरण में, मैं "i" के साथ क्या होता है, इस पर ध्यान दिए बिना, मैं (funcall f) हमेशा के लिए 10 वापस लौटना चाहता हूं। जब मैं अपने शरीर में फ़ंक्शन बनाया गया था, तो मैं "i" के मान को बांधने की कोशिश कर रहा हूं। –

+1

@DiogoFranco इनमें से पहला आप के लिए काम करेगा। बस दूसरे कार्य के साथ 'i' की स्थानीय प्रति का दायरा साझा न करें। (यदि आप बाहरी 'i' से 'let' को intialize करते हैं, तो आप दो' i' चर के साथ समाप्त हो जाएंगे: मूल बाहर, और 'let' द्वारा बनाई गई एक निजी प्रति।) – Leushenko

4

बस के मामले में ऊपर दो जवाब स्पष्टता में पर्याप्त नहीं है::

(defparameter *i* 10) 
;;Before you modify *i* 
(defvar f (let ((i *i*)) 
       #'(lambda() i))) 
;;Now f will always return 10 
(funcall f) => 10 
(incf *i*) => 11 
(funcall f) => 10 
+0

यह वास्तव में भ्रम का एक और संभावित बिंदु जोड़ता है, क्योंकि '* i *' 'defparameter 'के साथ घोषित किया गया है, और इस प्रकार * वैश्विक रूप से * विशेष घोषित किया गया है। इसका मतलब है कि '(चलो ((* i * * i *)) (lambda() * i)) * * काम नहीं करेगा। (यह वही नहीं है जैसा आपने किया था, लेकिन यह उल्लेख करना अच्छा होगा कि यदि एक विशेष चर को बाध्य करते हैं, तो समस्याएं होंगी। –