2013-08-18 4 views
9

http://www.aiai.ed.ac.uk/~jeff/lisp/cl-pitfalls राज्यों इस संशोधित कर सकते हैं के लिए बाहर देखने के लिएकैसे तथ्य यह है कि NREVERSE बजाय कारों कॉमन लिस्प से एक के रूप

विनाशकारी कार्यों आपको लगता है कि सीडीआर संशोधित बजाय कारों को संशोधित कर सकते हैं होगा नुकसान। (उदाहरण के लिए, NREVERSE।)

मुझे यकीन नहीं है कि मुझे क्या सावधानी बरतनी है। सामान्य सावधानी मैं इस तथ्य से ले सकता हूं कि NREVERSE सीडीआर संशोधित कर सकता है केवल NREVERSE का उपयोग करना है जब सूची (तर्क) किसी भी अन्य सूचियों के साथ पूंछ साझा नहीं करती है जो मेरे चर के बाद में संदर्भित हो सकता है (वेरिएबल को छोड़कर मैं वापसी मूल्य को बचाता हूं सेवा मेरे)। मुझे इस तथ्य से क्या सावधानी बरतनी चाहिए कि एनआरईआरईएसई कारों को संशोधित कर सकता है? यह देखने के लिए कुछ कैसे है?

उत्तर

12

किसी भी संदर्भ के बिना यह समझना बहुत मुश्किल है।

उदाहरण:

(setq list1 (list 1 2 3 4)) 

अब हम चार नंबर की एक सूची है। पहले विपक्ष के लिए परिवर्तनीय list1 अंक।

यदि हम एक विनाशकारी रिवर्स देखते हैं तो हम एक ऑपरेशन के बारे में बात कर रहे हैं जो विपक्षी कोशिकाओं को बदल सकता है। इस सूची को कैसे उलट किया जा सकता है इसके विभिन्न तरीके हैं।

हम उदाहरण के लिए विपक्षी कोशिकाओं को ले सकते हैं और उनसे उलट सकते हैं। पहला विपक्ष सेल आखिरी है। उस विपक्षी कोशिका के सीडीआर को NIL में बदलना होगा।

CL-USER 52 > (setq list1 (list 1 2 3 4)) 
(1 2 3 4) 

CL-USER 53 > (nreverse list1) 
(4 3 2 1) 

अब हमारे चर list1 अब भी वही विपक्ष सेल की ओर इशारा करता है, लेकिन इसकी सीडीआर बदल दिया गया है:

CL-USER 54 > list1 
(1) 

यकीन है कि एक उलट सूची में चर अंक, प्रोग्रामर तो है कि बनाने के लिए चर को अद्यतन करने के लिए कर्तव्य और nreverse ऑपरेशन के परिणामस्वरूप सेट करें। किसी भी अंतिम परिणाम के लिए list1 अंक देखने योग्य परिणाम का फायदा उठाने का लुत्फ उठाया जा सकता है।

उपरोक्त एक लिस्प डेवलपर आमतौर पर अपेक्षा करता है। रिवर्स का अधिकांश कार्यान्वयन इस तरह से काम करता प्रतीत होता है। लेकिन यह एएनएसआई सीएल मानक में निर्दिष्ट नहीं है कि कैसे nreverse लागू किया जाना है।

तो कारों को बदलने के लिए इसका क्या अर्थ होगा?

के nreverse का एक वैकल्पिक कार्यान्वयन पर नजर डालते हैं:

(defun nreverse1 (list) 
    (loop for e across (reverse (coerce list 'vector)) 
     for a on list do 
     (setf (car a) e)) 
    list) 

समारोह से ऊपर जाने विपक्ष कोशिकाओं बरकरार की श्रृंखला है, लेकिन कार बदल जाता है।

CL-USER 56 > (setq list1 (list 1 2 3 4)) 
(1 2 3 4) 

अब के नए संस्करण, nreverse1 उपयोग करते हैं।

CL-USER 57 > (nreverse1 list1) 
(4 3 2 1) 

CL-USER 58 > list1 
(4 3 2 1) 

अब आप अंतर देखते हैं: list1 अभी भी पूरी सूची को इंगित करता है।

सारांश: किसी को यह पता होना चाहिए कि nreverse के विभिन्न कार्यान्वयन संभव हैं। सामान्य व्यवहार का शोषण न करें, जहां एक चर फिर अंतिम विपक्ष को इंगित करेगा। बस nreverse के परिणाम का उपयोग करें और सबकुछ ठीक है।

साइड नोट: दूसरा संस्करण कहां उपयोग किया जा सकता है?

लिस्प मशीनों पर कुछ लिस्प कार्यान्वयन सूचियों में से एक कॉम्पैक्ट वेक्टर की तरह प्रतिनिधित्व की अनुमति दी। यदि इस तरह के लिस्प कार्यान्वयन पर कोई ऐसी सूची को रद्द कर देगा, तो कार्यान्वयनकर्ता एक कुशल वेक्टर-जैसे रिवर्स प्रदान कर सकते हैं।

+0

मैं अपने जवाब द्वारा +1 क्योंकि मैं विस्तृत दृष्टिकोण आप ले लिया पसंद है, लेकिन मुझे यकीन है कि अगर आप ओपी के प्रश्न का उत्तर है, जो है कैसे करने के लिए नहीं कर रहा हूँ इस तथ्य से निपटें कि 'nreverse' को कॉल करते समय 'कार' और 'सीडीआर' दोनों संभावित रूप से उत्परिवर्तित होते हैं। –

+6

@ क्रिस जेस्टर-यंग: इसके साथ * सौदा करने की कोई ज़रूरत नहीं है। बस एक विशेष कार्यान्वयन के एक विशेष दुष्प्रभाव का फायदा न लें। बस 'nreverse' के लौटे परिणाम का उपयोग करें। –

+1

मैं मानता हूँ, _if_ सूची आप में गुजर रहे हैं कोई उपनाम है। अन्यथा, आप सभी प्रकार की परेशानी में भाग लेते हैं। विशेष रूप से, योजना में कई सूची प्रक्रियाएं होती हैं जो साझा-पूंछ के परिणाम लौटाती हैं, जो अलियासिंग का एक रूप है। उदाहरण के लिए, 'append' का परिणाम और' संलग्न! '(' nconc') दिया पिछले सूची के साथ शेयरों पूंछ है, तो बुला 'रिवर्स!' ('nreverse') उस पर समस्याग्रस्त किया जा सकता है (अगर पूंछ के साथ सूची -श्रेषण का इस्तेमाल कहीं और किया जा रहा है)। –

3

किसी भी मामले में, यह कार या सीडीआर की विपक्ष सेल संशोधित, आप NREVERSE उपयोग नहीं करना चाहिए अगर पारित सूची के किसी भी विपक्ष सेल (पहले विपक्ष सेल सहित) एक और सूची के साथ साझा किया जा सकता हो। इसके बजाय रिवर्स का प्रयोग करें।

Btw, clisp वास्तव में सीएआर को संशोधित करता है:

> (let ((a (list 1 2 3 4 5 6 7 8 9 0))) 
    (nreverse a) 
    a) 
(0 9 8 7 6 5 4 3 2 1) 
संबंधित मुद्दे