2010-12-30 13 views
6

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

उदाहरण के लिए यदि आप लिस्पे मैक्रोज़ को उदाहरण देते हैं तो आप कैसे व्याख्या करेंगे?

+0

संबंधित: http://stackoverflow.com/questions/267862/what-makes-lisp-macros-so- विशेष – jball

+3

मुझे लगता है कि मैक्रोज़ के लिए सर्वोत्तम परिचय में से एक है [प्रैक्टिकल कॉमन लिस्प] (http: // gigamonkeys.com/book/practical-a-simple-database.html)। यह पहले अध्यायों में से एक है, इसलिए यह बहुत अधिक नहीं लगता है, और यह इतना लंबा नहीं है। पूरी किताब महान है, किसी के लिए अत्यधिक अनुशंसा की जाती है, "जेनेरिक" प्रोग्रामर या नहीं (सामान्य प्रोग्रामिंग पर अध्याय भी हैं!)। _forgot_ के लिए – spacemanaki

उत्तर

6

न्यू जबकि बयान

आपकी भाषा डिजाइनर थोड़ी देर के बयान भूल गया। आपने उसे कई बार मेल किया है। कोई सफलता नहीं। आपने भाषा संस्करण 2.5, 2.6 से 3.0 तक प्रतीक्षा की है। कुछ नहीं हुआ ...

लिस्प में:

हो गया (defmacro जबकि ... आपके जबकि कार्यान्वयन यहाँ ... सम्मिलित)।

LOOP का उपयोग करके मामूली कार्यान्वयन एक मिनट लेता है। विनिर्देशों

से

कोड पीढ़ी तो फिर तुम (CDRs) पार्स करने के लिए विस्तार से रिकॉर्ड कॉल कर सकते हैं। आपके पास फ़ील्ड विवरण के साथ रिकॉर्ड नाम हैं। अब मैं उनमें से प्रत्येक के लिए कक्षाएं और विधियां लिख सकता हूं। मैं कुछ कॉन्फ़िगरेशन प्रारूप का आविष्कार भी कर सकता हूं, कॉन्फ़िगरेशन फ़ाइल को पार्स कर सकता हूं और कक्षाएं बना सकता हूं। लिस्प में मैं एक मैक्रो लिखूंगा जो कोड को कॉम्पैक्ट विवरण से उत्पन्न करता है।

Domain Specific Languages in Lisp देखें, एक स्क्रीनकास्ट एक साधारण मैक्रो आधारित सामान्यीकरण के लिए एक काम कर रहे स्केच से एक सामान्य विकास चक्र दिखा रहा है।

कोड को फिर से लिखने

कल्पना कीजिए कि आप गेटर फ़ंक्शन का उपयोग की वस्तुओं के स्लॉट का उपयोग करने की है। अब कल्पना करें कि आपको कुछ कोड क्षेत्र में कई वस्तुओं को कई बार एक्सेस करने की आवश्यकता है। अस्थायी चर का उपयोग कर किसी कारण से कोई समाधान नहीं है।

... 
... (database-last-user database) ... 
... 

अब आप एक मैक्रो के साथ एक पत्र लिख सकते हैं जो गेटर अभिव्यक्ति के लिए प्रतीक प्रस्तुत करता है।

(with-getters (database (last-user database-last-user)) 
    ... 
    ... last-user 
    ...) 

मैक्रो संलग्न ब्लॉक के अंदर स्रोत को फिर से लिख देगा और सभी निर्दिष्ट प्रतीकों को गेटर अभिव्यक्ति के साथ प्रतिस्थापित करेगा।

+0

+1। :-) (बाकी का जवाब भी अच्छा है, लेकिन, मुझे उस बिट को विशेष रूप से पसंद आया।) –

1

मुझे सीएल काफी अच्छी तरह से नहीं पता, लेकिन योजना मैक्रोज़ करेगा? यहाँ योजना में थोड़ी देर के पाश है:

(define-syntax while 
    (syntax-rules() 
    ((while pred body ...) 
    (let loop() 
     (if pred (begin body ... (loop))))))) 

इस मामले में, उदाहरण दर्शाता है कि आप आसानी से मैक्रो का उपयोग कर अपने स्वयं के नियंत्रण संरचनाओं लिख सकते हैं। foof-loop और भी उपयोगी लूपिंग संरचनाओं का संग्रह है (शायद सीएल के कुछ भी नया नहीं है, लेकिन प्रदर्शन के लिए अभी भी अच्छा है)।


एक अन्य उपयोग केस: सहयोगी सूचियों से मूल्यों को चुनना। उपयोगकर्ताओं को अपने कार्य में विकल्पों के रूप में एक अलगाव में पास कहें। आप आसानी से इस मैक्रो का उपयोग करके मूल्यों बाहर ले सकते हैं:

(define-syntax let-assq 
    (syntax-rules() 
    ((let-assq alist (key) body ...) 
    (let ((key (assq-ref alist 'key))) 
     body ...)) 
    ((let-assq alist (key rest ...) body ...) 
    (let ((key (assq-ref alist 'key))) 
     (let-assq alist (rest ...) body ...))))) 

;; Guile built-in 
(define (assq-ref alist key) 
    (cond ((assq key alist) => cdr) 
     (else #f))) 

उदाहरण उपयोग:

(define (binary-search tree needle (lt? <)) 
    (let loop ((node tree)) 
    (and node 
     (let-assq node (value left right) 
      (cond ((lt? needle value) (loop left)) 
       ((lt? value needle) (loop right)) 
       (else value)))))) 

सूचना कैसे let-assq मैक्रो के बिना "नोड" से value, left, और right कुंजी चुनने की अनुमति देता है let फ़ॉर्म लिखने के लिए बहुत लंबा है।

7

मेरे अनुभव से, मैक्रो लोगों पर सबसे अच्छा प्रभाव बनाने के लिए जब वे देखें कि यह कैसे कोड, कि प्रक्रियाओं या अन्य निर्माणों से नहीं बनाया जा सकता उत्पादन करने के लिए मदद करता है। अक्सर इस तरह की चीजों को वर्णित किया जा सकता है:

<common code> 
<specific code> 
<other common code> 

जहां <common code> हमेशा समान होता है। यहां इस तरह के स्कीमा के कुछ उदाहरण दिए गए हैं:

1. time मैक्रो। मैक्रो के बिना एक भाषा में कोड कुछ इस तरह दिखेगा:

int startTime = getCurrentTime(); 
<actual code> 
int endTime = getCurrentTime(); 
int runningTime = endTime - startTime; 

आप नहीं, प्रक्रिया के लिए सभी आम कोड डाल सकते हैं, क्योंकि यह वास्तविक कोड इर्द-गिर्द घूमती। (ठीक है, यदि आप भाषा का समर्थन करते हैं, तो आप लैम्बडा फ़ंक्शन में एक प्रक्रिया बना सकते हैं और वास्तविक कोड पास कर सकते हैं, लेकिन यह हमेशा सुविधाजनक नहीं होता है)।
और, जैसा कि आप सबसे शायद जानते हैं, लिस्प में आप सिर्फ time मैक्रो बनाते हैं और इसे करने के लिए वास्तविक कोड पारित:

(time 
    <actual code>) 

2. लेन-देन। पूछो जावा प्रोग्रामर JDBC के साथ सरल SELECT के लिए विधि लिखने के लिए - यह संबंध और लेनदेन को खोलने के लिए 14-17 लाइनों लेने के लिए और कोड शामिल होंगे, उन्हें बंद करने के लिए, कई नेस्टेड try-catch-finally बयानों और अद्वितीय कोड का केवल 1 या 2 लाइनों।
लिस्प में आप बस with-connection मैक्रो लिखें और कोड को 2-3 लाइनों तक कम करें।

3. तुल्यकालन। ठीक है, जावा, सी # और अधिकांश आधुनिक भाषाओं में पहले से ही इसके लिए बयान हैं, लेकिन अगर आपकी भाषा में ऐसा कोई निर्माण नहीं है तो क्या करें? या यदि आप STM-आधारित लेनदेन जैसे नए प्रकार के सिंक्रनाइज़ेशन को पेश करना चाहते हैं? दोबारा, आपको इस कार्य के लिए अलग-अलग वर्ग लिखना चाहिए और मैन्युअल रूप से इसके साथ काम करना चाहिए, यानी प्रत्येक कथन के चारों ओर सामान्य कोड डालें जिसे आप सिंक्रनाइज़ करना चाहते हैं।

केवल कुछ उदाहरण था। आप उल्लेख कर सकते हैं with-open श्रृंखला की तरह मैक्रो "नहीं करने के लिए भूल जाते हैं", कि सफाई पर्यावरण और संसाधन लीक, कई if रों के बजाय cond जैसे नए निर्माणों मैक्रो से बचाने के लिए, और, ज़ाहिर है, आलसी निर्माणों के बारे में भूल नहीं है जैसे if, or और and, जो उनके तर्कों का मूल्यांकन नहीं करते हैं (प्रक्रिया अनुप्रयोग के विपरीत)।

कुछ प्रोग्रामर वकील हो सकते हैं कि उनकी भाषा में इस या उस मामले (ओआरएम, एओपी, आदि) का इलाज करने की तकनीक है, लेकिन उनसे पूछें, क्या मैक्रोज़ मौजूद होने पर इन सभी तकनीकों की आवश्यकता होगी?

तो, इसे पूरी तरह से लेना और मैक्रोज़ को समझाने के तरीके के बारे में मूल प्रश्न का उत्तर देना। जावा (सी #, सी ++, आदि) में किसी भी व्यापक रूप से इस्तेमाल किए गए कोड को ले जाएं, इसे लिस्प में बदलें और फिर इसे मैक्रो के रूप में फिर से लिखें।

0

मै मैक्रोज़ को कार्यों के समान (या दोहरी) के रूप में एक अमूर्तता के रूप में देखते हैं, सिवाय इसके कि आप तर्कों का मूल्यांकन कब और कैसे कर सकते हैं। यह रेखांकित करता है कि मैक्रोज़ उपयोगी क्यों हैं - कोड की नकल को रोकने और रखरखाव को कम करने के लिए फ़ंक्शंस की तरह ही।

मेरा पसंदीदा उदाहरण एनाफोरिक मैक्रोज़ हैं। एआईएफ, थोड़ी देर या aand तरह:

(defmacro aif (test-form then-form &optional else-form) 
    `(let ((it ,test-form)) 
    (if it ,then-form ,else-form))) 

    (defmacro awhile (expr &body body) 
     `(do ((it ,expr ,expr)) ((not it)) 
     ,@body)) 

    (defmacro aand (&rest args) 
     (cond 
     ((null args) t) 
     ((null (cdr args)) (car args)) 
     (t `(aif ,(car args) (aand ,@(cdr args)))))) 

ये बहुत सरल कर रहे हैं और लिखने का बहुत सा बचा सकता है।

0

ऐसा कुछ नहीं है जिसे आप थोड़े समय में समझा सकते हैं, ठीक है, मैक्रो की अवधारणा को एक वाक्य में समझाया जा सकता है और एक उदाहरण जैसे कि समझने में काफी आसान है, समस्या यह है कि वह व्यक्ति वास्तव में समझ में नहीं आता क्यों मैक्रोज़ केवल ऐसे छोटे उदाहरणों के साथ एक अच्छी बात है।

3

के बाद से ठोस उदाहरण भाषा आप उन्हें में लिख रहे हैं के विवरण में करना शुरू कर सकता, एक गैर ठोस लेकिन जोड़ा जा बयान पर विचार करें:

"तुम सब है कि बॉयलरप्लेट कोड है कि आप कभी कभी लिखने की पता ? आपको कभी भी लिस्पर में बॉयलरप्लेट लिखना नहीं है, क्योंकि आप हमेशा यह करने के लिए कोड जनरेटर लिख सकते हैं। "

'बॉयलरप्लेट' द्वारा, मैं जावा में एक-एक इंटरफ़ेस कार्यान्वयन के बारे में सोच रहा हूं, सी ++ में अंतर्निहित रचनाकारों को ओवरराइड कर रहा हूं, लिखना() - सेट() जोड़े, आदि लिख रहा हूं। मुझे लगता है कि यह अशिष्ट रणनीति कोशिश करने से बेहतर काम कर सकती है मैक्रोज़ को बहुत अधिक विस्तार से समझाने के लिए, क्योंकि वह शायद बॉयलरप्लेट के विभिन्न रूपों से परिचित हैं, जबकि उन्होंने कभी मैक्रो नहीं देखा है।

-1

नहीं, ऐसा नहीं है। मैक्रोज़ को स्पष्ट रूप से समझने के लिए किसी को लिस्प से परिचित होना चाहिए।

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