2012-01-22 9 views
15

क्या कोई निम्नलिखित व्यवहार को समझा सकता है? विशेष रूप से, फ़ंक्शन हर बार एक अलग सूची क्यों देता है? some-list क्यों नहीं कहा जाता है जब हर बार समारोह कहा जाता है '(0 0 0)?यह फ़ंक्शन हर बार एक अलग मूल्य क्यों देता है?

(defun foo() 
    (let ((some-list '(0 0 0))) 
    (incf (car some-list)) 
    some-list)) 

आउटपुट:

> (foo) 
(1 0 0) 
> (foo) 
(2 0 0) 
> (foo) 
(3 0 0) 
> (foo) 
(4 0 0) 

धन्यवाद!

संपादित करें:

इसके अलावा, क्या इस समारोह को लागू करने, यह मानते हुए की सिफारिश की तरह से मैं उत्पादन '(1 0 0) हर बार करने के लिए समारोह चाहते है?

उत्तर

21

'(0 0 0) एक शाब्दिक वस्तु है, जो (यद्यपि संशोधन से संरक्षित नहीं) एक स्थिर माना जाता है। तो आप हर बार एक ही ऑब्जेक्ट को प्रभावी ढंग से संशोधित कर रहे हैं। प्रत्येक फंक्शन कॉल पर विभिन्न ऑब्जेक्ट्स बनाने के लिए (list 0 0 0) का उपयोग करें।

तो जब तक आप नहीं जानते कि आप क्या कर रहे हैं, आपको हमेशा शाब्दिक सूचियों (जैसे '(0 0 0)) का उपयोग केवल स्थिरांक के रूप में करना चाहिए।

+0

आह, अब समझ में आता है। स्पष्ट स्पष्टीकरण के लिए धन्यवाद। –

+2

शायद यह जोड़ना अच्छा होगा कि quasiquoting भी ताजा सूचियों को वापस करने की गारंटी नहीं है। – 6502

+3

"जब तक आप नहीं जानते, आप क्या कर रहे हैं" शाब्दिक डेटा को संशोधित करने का व्यवहार अपरिभाषित है। Spec के अनुसार, आप वास्तव में नहीं जानते कि आप क्या कर रहे हैं (निश्चितता के साथ), तो "आपको हमेशा ** ** शाब्दिक सूचियों (जैसे '(0 0 0)) केवल स्थिरांक के रूप में उपयोग करना चाहिए"। –

-5

एक अपने आप को लिखने के लिए चाहता था, लेकिन मैं एक अच्छा ऑनलाइन पाया:

CommonLisp प्रथम श्रेणी कार्य करता है, अर्थात कार्यों वस्तुओं जो रनटाइम पर बनाया जा सकता है, और अन्य कार्यों के लिए तर्क के रूप में पारित कर दिया। --अलेनपार्ड इन प्रथम श्रेणी के कार्यों में भी अपना स्वयं का राज्य है, इसलिए वे मज़ेदार हैं। सभी लिस्प फ़ंक्शन फ़ैक्टर हैं; "बस कोड" और "फ़ंक्शन ऑब्जेक्ट्स" वाले फ़ंक्शंस के बीच अलगाव नहीं है। राज्य कैप्चर लेक्सिकल वेरिएबल बाइंडिंग का रूप लेता है। बाइंडिंग कैप्चर करने के लिए आपको LAMBDA का उपयोग करने की आवश्यकता नहीं है; एक उच्च-स्तरीय defun यह भी कर सकते हैं: (((निजी-चर 42)) (defun foo जाने() ...))

... के स्थान पर कोड निजी चर देखता है अपने अक्षीय दायरे में। एक से जुड़े इस चर का एक उदाहरण है और केवल फ़ंक्शन ऑब्जेक्ट है जो वैश्विक रूप से प्रतीक खाद्य से जुड़ा हुआ है; DE12UN अभिव्यक्ति का मूल्यांकन होने पर वैरिएबल कैप्चर किया जाता है। यह चर फिर सी या Or, में स्थिर चर की तरह कुछ कार्य करता है, आप फूड्स को "इंस्टेंस चर" के साथ "सिंगलटन" ऑब्जेक्ट के रूप में सोच सकते हैं। --KazKylheku

रेफरी http://c2.com/cgi/wiki?CommonLisp

+1

क्या आप समझा सकते हैं कि आपके द्वारा उद्धृत पाठ कैसे प्रश्न से संबंधित है? मुझे कुछ याद आ रहा है, लेकिन मुझे यह नहीं दिख रहा है। – sepp2k

+0

पाठ बताता है कि लिस्प में प्रथम श्रेणी की वस्तुएं कैसे कार्य करती हैं, और वास्तव में "स्थिति" होती है। घोषित चर समारोह के "राज्य" का हिस्सा था। जैसा कि पाठ बताता है, यह सी में स्थैतिक स्थानीय चर घोषित करने के समान ही है। पाठ का कौन सा हिस्सा इस समस्या से संबंधित नहीं है? – xtrem

+2

वह हिस्सा जहां यह सब कुछ नहीं हो रहा है। आपका उद्धरण "कैप्चर लेक्सिकल वैरिएबल बाइंडिंग" के बारे में बात करता है। हालांकि 'कुछ-सूची' 'foo' का स्थानीय चर है, यह एक कैप्चर वैरिएबल नहीं है और इस प्रकार 'foo' के राज्य का हिस्सा नहीं है। 'Foo' के प्रत्येक आमंत्रण पर,' कुछ-सूची 'में एक अद्वितीय बाध्यकारी होगा (जैसा कि Vsevolod समझाया गया है, वही "स्थिर" सूची को इंगित करेगा, जो ओपी के व्यवहार को बताता है)। यह कैप्चर किए गए चर को संशोधित करने वाले फ़ंक्शन से बिल्कुल अलग है। – sepp2k

9

एक तरफ ध्यान दें पर, SBCL आरईपीएल आप निम्न चेतावनी मिल में इस समारोह को परिभाषित:

caught WARNING: 
    Destructive function SB-KERNEL:%RPLACA called on constant data. 
    See also: 
     The ANSI Standard, Special Operator QUOTE 
     The ANSI Standard, Section 3.2.2.3 

कौन सा हाथ में समस्या की दिशा में एक अच्छा संकेत देता है।

4

'(0 0 0) कोड में शाब्दिक डेटा है। इस डेटा को संशोधित करने में अपरिभाषित व्यवहार है। सामान्य लिस्प कार्यान्वयन इसे रनटाइम पर नहीं ढूंढ सकता है (जब तक कि डेटा कुछ पढ़ने-योग्य स्मृति स्थान में नहीं रखा जाता है)। लेकिन यह अवांछनीय प्रभाव हो सकता है।

  • आप देखते हैं कि इस डेटा हो सकता है (और अक्सर है) एक ही समारोह

  • अधिक सूक्ष्म संभावित त्रुटियों में से एक के विभिन्न आमंत्रण पर साझा किया जाता है: कॉमन लिस्प विभिन्न अनुकूलन के साथ परिभाषित किया गया है जो एक कंपाइलर द्वारा दिमाग में किया जा सकता है।

    (let ((a '(1 2 3)) 
         (b '(1 2 3))) 
        (list a b)) 
    

    उपरोक्त कोड में झलकी संकलक पता लगा सकता है कि a और b का शाब्दिक डेटा EQUAL है:

उदाहरण: उदाहरण के लिए एक संकलक डेटा पुन: उपयोग करने की अनुमति है। इसके बाद दोनों चर एक ही शाब्दिक डेटा को इंगित कर सकते हैं। इसे संशोधित करना काम कर सकता है, लेकिन परिवर्तन a और b से दिखाई दे रहा है।

सारांश: शाब्दिक डेटा का संशोधन कई सूक्ष्म बग का स्रोत है। यदि संभव हो तो इसे से बचें। फिर आपको विपक्ष नई डेटा ऑब्जेक्ट्स की आवश्यकता है। सामान्य रूप से का उपभोग करना मतलब है कि रनटाइम पर ताजा, नए डेटा संरचनाओं का आवंटन।