2015-05-07 6 views
6

अगर मैं गलत हूं, तो मुझे सही करें, लेकिन जावा, सी, सी ++, पायथन, जावास्क्रिप्ट, या मैंने उपयोग की जाने वाली किसी अन्य भाषा में जेनसिम जैसी कुछ भी नहीं है, और मुझे इसकी आवश्यकता नहीं है। लिस्प में क्यों जरूरी है और अन्य लंगुओं में नहीं? स्पष्टीकरण के लिए, मैं आम लिस्प सीख रहा हूं।lisp gensym और अन्य भाषाओं का उपयोग क्यों नहीं करता है?

+0

जीन्सिम वास्तव में जावा में जो कुछ भी आप नए प्रतीक ("foo") के साथ करते हैं उससे अलग नहीं है; '। प्रतीकों का * interning * वास्तव में और अधिक दिलचस्प है (लेकिन बिल्कुल अद्वितीय नहीं)। इंटर्न प्रतीकों के लिए फैक्ट्री विधि की तरह है, जहां आप एक ही बना सकते हैं यदि आपने पहले ऐसा ही बनाया था; gensym एक निर्माता की तरह है जहां आप हमेशा कुछ नया मिलता है। –

उत्तर

6

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

सामान्य लिस्प में आप gensym का उपयोग करते हैं जब आप कोड बनाना चाहते हैं जहां प्रतीक परिणाम में किसी अन्य स्थान का उपयोग करने वाले तत्वों से मेल नहीं खाता है। इसके बिना इस बात की कोई गारंटी नहीं है कि उपयोगकर्ता एक प्रतीक का उपयोग करता है जो मैक्रो कार्यान्वयनकर्ता भी उपयोग करता है और वे हस्तक्षेप करना शुरू करते हैं और परिणाम इच्छित व्यवहार से कुछ अलग होता है। यह सुनिश्चित करता है कि उसी मैक्रो का घोंसला विस्तार पिछले विस्तारों में हस्तक्षेप न करे। सामान्य लिस्प मैक्रो सिस्टम के साथ योजना syntax-rules और syntax-case के समान अधिक प्रतिबंधक मैक्रो सिस्टम बनाना संभव है।

योजना में कई मैक्रो सिस्टम हैं। एक पैटर्न मिलान के साथ जहां नए पेश किए गए प्रतीक स्वचालित रूप से कार्य करते हैं जैसे कि वे gensym के साथ बनाए जाते हैं। syntax-case डिफ़ॉल्ट रूप से नए प्रतीक भी बनाएगा जैसे कि वे gensym के साथ बनाए गए थे और स्वच्छता को कम करने का एक तरीका भी है। आप syntax-case के साथ सीएल defmacro बना सकते हैं लेकिन चूंकि योजना में gensym नहीं है, इसलिए आप इसके साथ स्वच्छ मैक्रोज़ बनाने में सक्षम नहीं होंगे।

जावा, सी, सी ++, पायथन, जावास्क्रिप्ट सभी Algol dialects हैं और इनमें से कोई भी सरल टेम्पलेट आधारित मैक्रोज़ के अलावा अन्य नहीं है। इस प्रकार उनके पास gensym नहीं है क्योंकि उन्हें इसकी आवश्यकता नहीं है। चूंकि इन भाषाओं में नए वाक्यविन्यास को पेश करने का एकमात्र तरीका यह है कि इसके अगले संस्करण की इच्छा होगी।

शक्तिशाली मैक्रोज़ के साथ दो अल्गोल बोलियां हैं जो दिमाग में आती हैं। Nemerle और Perl6। उनमें से दोनों में स्वच्छता दृष्टिकोण है, जिसका अर्थ वैरिएबल पेश किया गया है जैसे कि वे gensym के साथ बने हैं।

सीएल, योजना, नेमेरले, पर्ल 6 में आपको भाषा सुविधाओं की प्रतीक्षा करने की आवश्यकता नहीं है।आप उन्हें स्वयं बना सकते हैं! जावा और PHP दोनों में खबरों को आसानी से मैक्रोज़ के साथ कार्यान्वित किया जाता है, उनमें से किसी भी में यह पहले से ही उपलब्ध नहीं होना चाहिए।

+0

जावास्क्रिप्ट में, आप एक नया चर परिभाषित करने के लिए "var" का उपयोग करते हैं और इसे सबसे प्रतिबंधित लेक्सिकल स्कोप तक सीमित करते हैं। क्या Gensym का उपयोग किया जाता है क्योंकि सीएल में "var" की तरह कुछ नहीं है? – michaelAdam

+0

@ माइकलएडम जावास्क्रिप्ट में शक्तिशाली मैक्रोज़ नहीं हैं। उदाहरण के लिए। 'Cond' कार्यान्वित करें ताकि यह 'cond (अभिव्यक्ति) {...} (अभिव्यक्ति 2) {...} अन्य {...}' – Sylwester

+0

काम करता है, मुझे लगता है कि मैं इसे अब समझता हूं। मैक्रोज़ और फ़ंक्शंस के बीच वास्तविक अंतर को समझ में नहीं आया और मैक्रो में चर को फ़ंक्शन में सावधानीपूर्वक स्कॉप्ड नहीं किया जा सकता है। एक फ़ंक्शन में, आप जो भी चाहें लेक्सिकल वैरिएबल नाम देने के लिए स्वतंत्र हैं क्योंकि आप केवल किसी मान के संदर्भ से निपट रहे हैं, और इसका नाम बदलना इसके मूल्य को नहीं बदलता है। एक मैक्रो के तर्क वैरिएबल वाले वैरिएबल नहीं होते हैं, उनमें कोड होता है। उस कोड के भीतर अभिव्यक्तियों के नाम मनमाने ढंग से नहीं हैं, वे मैक्रो के पर्यावरण से आते हैं और इसका उत्पादन निर्धारित करते हैं। – michaelAdam

8

यह नहीं कह सकता कि कौन सी भाषाओं में GENSYM के बराबर है। कई भाषाओं में प्रथम श्रेणी का प्रतीक डेटा प्रकार नहीं होता है (आंतरिक और अनियंत्रित प्रतीकों के साथ) और कई समान कोड जनरेशन (मैक्रोज़, ...) सुविधाएं प्रदान नहीं कर रहे हैं।

एक आंतरिक प्रतीकपैकेज में पंजीकृत है। एक अनइंटर नहीं है। यदि पाठक (पाठक लिस्प उपप्रणाली है जो इनपुट के रूप में टेक्स्ट एस-एक्सप्रेशन लेता है और डेटा लौटाता है) उसी पैकेज में दो आंतरिक प्रतीकों को देखता है और उसी नाम से, यह मानता है कि यह एक ही प्रतीक है:

CL-USER 35 > (eq 'cl:list 'cl:list) 
T 

पाठक एक uninterned प्रतीक देखता है, यह उसकी जगह एक नया:

CL-USER 36 > (eq '#:list '#:list) 
NIL 

uninterned प्रतीकों नाम के सामने #: साथ लिखा जाता है।

GENSYMगिने uninterned प्रतीकों बनाने के लिए है, क्योंकि यह कभी कभी कोड पीढ़ी में उपयोगी है और उसके बाद इस कोड डिबगिंग लिस्प में प्रयोग किया जाता है। ध्यान दें कि प्रतीक हमेशा नए होते हैं और eq किसी अन्य चीज़ पर नहीं होते हैं। लेकिन प्रतीक का नाम किसी अन्य प्रतीक के नाम के समान ही हो सकता है। संख्या पहचान के बारे में मानव पाठक को एक सुराग देता है।

MAKE-SYMBOL

make-symbol का उपयोग कर एक उदाहरण अपने नाम के रूप में एक स्ट्रिंग तर्क उपयोग कर एक नया uninterned प्रतीक बनाता है।

के इस समारोह कुछ कोड जनरेट देखते हैं:

CL-USER 31 > (defun make-tagbody (exp test) 
       (let ((start-symbol (make-symbol "start")) 
        (exit-symbol (make-symbol "exit"))) 
       `(tagbody ,start-symbol 
          ,exp 
          (if ,test 
           (go ,start-symbol) 
          (go ,exit-symbol)) 
          ,exit-symbol))) 
MAKE-TAGBODY 

CL-USER 32 > (pprint (make-tagbody '(incf i) '(< i 10))) 

(TAGBODY 
#:|start| (INCF I) 
     (IF (< I 10) (GO #:|start|) (GO #:|exit|)) 
#:|exit|) 

उत्पन्न कोड से ऊपर uninterned प्रतीकों का उपयोग करता। #:|start| दोनों वास्तव में एक ही प्रतीक हैं। हम यह देखेंगे यदि हमारे पास *print-circle* से T होगा, क्योंकि प्रिंटर तब स्पष्ट वस्तुओं को स्पष्ट रूप से लेबल करेगा। लेकिन यहां हमें यह अतिरिक्त जानकारी नहीं मिली है। अब यदि आप इस कोड को घोंसला करते हैं, तो आप एक start और एक exit प्रतीक से अधिक देखेंगे, प्रत्येक जो दो स्थानों पर उपयोग किया गया था।

GENSYM

का उपयोग कर अब gensym का उपयोग करते हैं एक उदाहरण। जेन्सेम भी एक अनियंत्रित प्रतीक बनाता है। वैकल्पिक रूप से इस प्रतीक को एक स्ट्रिंग द्वारा नामित किया गया है। एक संख्या (चर CL:*GENSYM-COUNTER* देखें) जोड़ा गया है।

CL-USER 33 > (defun make-tagbody (exp test) 
       (let ((start-symbol (gensym "start")) 
        (exit-symbol (gensym "exit"))) 
       `(tagbody ,start-symbol 
          ,exp 
          (if ,test 
           (go ,start-symbol) 
          (go ,exit-symbol)) 
          ,exit-symbol))) 
MAKE-TAGBODY 

CL-USER 34 > (pprint (make-tagbody '(incf i) '(< i 10))) 

(TAGBODY 
#:|start213051| (INCF I) 
     (IF (< I 10) (GO #:|start213051|) (GO #:|exit213052|)) 
#:|exit213052|) 

अब नंबर एक संकेतक है कि दो uninterned #:|start213051| प्रतीकों वास्तव में एक ही कर रहे हैं।,

CL-USER 7 > (pprint (make-tagbody `(progn 
            (incf i) 
            (setf j 0) 
            ,(make-tagbody '(incf ij) '(< j 10))) 
            '(< i 10))) 

(TAGBODY 
#:|start2756| (PROGN 
       (INCF I) 
       (SETF J 0) 
       (TAGBODY 
        #:|start2754| (INCF IJ) 
          (IF (< J 10) 
           (GO #:|start2754|) 
          (GO #:|exit2755|)) 
        #:|exit2755|)) 
     (IF (< I 10) (GO #:|start2756|) (GO #:|exit2757|)) 
#:|exit2757|) 

इस प्रकार यह मदद करता है समझ उत्पन्न कोड पर *print-circle* चालू करने के लिए है, जो समान वस्तुओं लेबल होगा की आवश्यकता के बिना:: जब कोड नेस्ट किया जाएगा, शुरू प्रतीक के नए संस्करण एक अलग संख्या के लिए होता है

CL-USER 8 > (let ((*print-circle* t)) 
       (pprint (make-tagbody `(progn 
             (incf i) 
             (setf j 0) 
             ,(make-tagbody '(incf ij) '(< j 10))) 
            '(< i 10)))) 

(TAGBODY 
#3=#:|start1303| (PROGN 
        (INCF I) 
        (SETF J 0) 
        (TAGBODY 
        #1=#:|start1301| (INCF IJ) 
          (IF (< J 10) (GO #1#) (GO #2=#:|exit1302|)) 
        #2#)) 
     (IF (< I 10) (GO #3#) (GO #4=#:|exit1304|)) 
#4#) 

ऊपर लिस्प पाठक (सबसिस्टम जो पढ़ता शाब्दिक अभ्यावेदन के लिए स-भाव) के लिए पठनीय है, लेकिन मानव पाठक के लिए थोड़ा कम।

1

मेरा मानना ​​है कि symbols (लिस्प अर्थ में) अधिकतर homoiconic भाषाओं में उपयोगी होते हैं (जिनमें भाषा का वाक्यविन्यास उस भाषा के डेटा के रूप में प्रतिनिधित्व योग्य होता है)।

जावा, सी, सी ++, पायथन, जावास्क्रिप्ट homoiconic नहीं हैं।

एक बार आपके पास प्रतीक होने के बाद, आप उन्हें गतिशील रूप से बनाने के लिए कुछ तरीका चाहते हैं। gensym एक संभावना है, लेकिन आप उन्हें intern भी कर सकते हैं।

बीटीडब्ल्यू, MELT एक लिस्पी जैसी बोली है, यह gensym के साथ या तारों को प्रशिक्षित करके clone_symbol के साथ प्रतीक नहीं बनाता है। (वास्तव में एमईएलटी प्रतीक पूर्वनिर्धारित CLASS_SYMBOL, ...) के उदाहरण हैं।

0

gensym प्रोलॉग दुभाषियों के अधिकांश में एक अनुमान के रूप में उपलब्ध है। आप इसे उपनाम पुस्तकालय में पा सकते हैं।

संबंधित मुद्दे