2012-05-28 20 views
7

मान लीजिए कि मैं एस-अभिव्यक्ति में पहले आइटम के अलावा किसी अन्य चीज़ पर स्कीम मैक्रो ट्रिगर करना चाहता हूं। उदाहरण के लिए, कि मैं एक इन्फ़िक्स शैली := साथ define को बदलने के लिए करना चाहता था लगता है, तो यह है कि:स्कीम मैक्रो जो खोजशब्द द्वारा ट्रिगर किया गया है

(a := 5) -> (define a 5) 
((square x) := (* x x)) -> (define (square x) (* x x)) 

वास्तविक परिवर्तन काफी सरल हो रहा है। इस चाल को := अभिव्यक्तियों और मैक्रो-विस्तारित करने के लिए योजना मिल जाएगी। मैंने कोड के आसपास के बड़े वर्गों के बारे में सोचा है जो मानक मैक्रो के साथ इंफिक्स सिंटैक्स का उपयोग करते हैं, शायद: (with-infix-define expr1 expr2 ...), और मानक मैक्रो अपने शरीर में अभिव्यक्तियों के माध्यम से चलना और आवश्यक परिवर्तन करना। मुझे पता है कि यदि मैं इस दृष्टिकोण को लेता हूं, तो मुझे उन सूचियों को बदलने से बचने के लिए सावधान रहना होगा जिन्हें वास्तव में डेटा माना जाता है, जैसे उद्धृत सूचियां, और quasiquoted सूचियों के कुछ अनुभाग। मैं क्या कल्पना का एक उदाहरण:

(with-infix-define 
    ((make-adder n) := (lambda (m) (+ n m))) 

    ((foo) := 
     (add-3 := (make-adder 3)) 
     (add-6 := (make-adder 6)) 
     (let ((a 5) (b 6)) 
      (+ (add-3 a) (add-6 b)))) 

    (display (foo)) 
    (display '(This := should not be transformed)) 

तो, मेरे सवाल का दो गुना है:

  1. अगर मैं with-infix-define मार्ग अपनाते हैं, मैं किसी भी ठोकर बोली के अलावा अन्य ब्लॉकों के लिए बाहर देखने के लिए करते हैं और quasiquote?
  2. मुझे लगता है कि मैं पहिया को फिर से शुरू कर रहा हूं। इस प्रकार का कोड चलना बिल्कुल मानक मैक्रो विस्तार प्रणालियों को करना होगा - केवल अंतर यह है कि किसी भी कोड परिवर्तन को करने या नहीं करने का निर्णय लेने पर वे केवल सूची में पहले आइटम को देखते हैं। क्या कोई तरीका है कि मैं मौजूदा सिस्टम पर बस पिगबैक कर सकता हूं?
+0

क्या योजना के लिए कोड-वॉकर पैकेज है? ऐसा लगता है कि आपको बस इतना करना है कि कोड को मैक्रो में लपेटें, उस कोड को चलाएं और स्वैप करें: = पिछले एस-एक्स के साथ, फिर एक प्रतीक मैक्रो परिभाषित करें जो बनाता है: = परिभाषित करने के बराबर। यद्यपि उद्धृत एस-एक्सप पर निश्चित नहीं है। –

उत्तर

12
  1. इससे पहले कि आप इस के साथ जारी है, यह सोचने के लिए अच्छी तरह से खत्म हो गया चीजें सबसे अच्छा है - IME आप अक्सर है कि क्या तुम सच में एक इन्फ़िक्स वाक्य रचना के रूप में := के पाठक स्तरीय हैंडलिंग चाहते हैं चाहते हैं। इसका मतलब यह होगा कि यह उद्धरण आदि में भी इंफिक्स है, इसलिए अब यह बुरा लगेगा, लेकिन फिर, मेरा अनुभव यह है कि आप यह महसूस कर रहे हैं कि चीजों को लगातार करना बेहतर है।

  2. पूर्णता के लिए, मैं रैकेट में है कि रीड-वाक्य रचना इन्फ़िक्स की तरह भाव के लिए हैक उल्लेख करेंगे: (x . define . 1)(define x 1) के रूप में पढ़ा है। (और ऊपर के रूप में, यह हर जगह काम करता है।)

  3. अन्यथा, एक रैपिंग मैक्रो का आपका विचार केवल एक चीज है जो आप कर सकते हैं। यह पूरी तरह निराशाजनक नहीं है, हालांकि, आपके कार्यान्वयन के विस्तारक में एक हुक हो सकता है जो आपको ऐसी चीजों को करने की अनुमति दे सकता है - उदाहरण के लिए, रैकेट के पास एक विशेष मैक्रो है जिसे #%module-begin कहा जाता है जो एक पूर्ण मॉड्यूल बॉडी और #%top-interaction को लपेटता है जो अपर्याप्त लपेटता है आरईपीएल पर अभिव्यक्तियां (इन दोनों के दो संदर्भों में परोक्ष जुड़ जाते हैं।) यहाँ एक उदाहरण (मैं रैकेट के define-syntax-rule सादगी के लिए उपयोग कर रहा हूँ) है:

    #lang racket/base 
    
    (provide (except-out (all-from-out racket/base) 
            #%module-begin #%top-interaction) 
         (rename-out [my-module-begin #%module-begin] 
            [my-top-interaction #%top-interaction])) 
    
    (define-syntax infix-def 
        (syntax-rules (:= begin) 
        [(_ (begin E ...)) (begin (infix-def E) ...)] 
        [(_ (x := E ...)) (define x (infix-def E) ...)] 
        [(_ E)    E])) 
    
    (define-syntax-rule (my-module-begin E ...) 
        (#%module-begin (infix-def E) ...)) 
    (define-syntax-rule (my-top-interaction . E) 
        (#%top-interaction . (infix-def E))) 
    

    अगर मैं my-lang.rkt नामक एक फ़ाइल में इस डाल, मैं अब यह के रूप में उपयोग कर सकते हैं इस प्रकार है:

    #lang s-exp "my-lang.rkt" 
    (x := 10) 
    ((fib n) := 
    (done? := (<= n 1)) 
    (if done? n (+ (fib (- n 1)) (fib (- n 2))))) 
    (fib x) 
    
  4. हाँ, आप चीजों की एक गुच्छा के साथ सौदा करने की जरूरत है। उपर्युक्त में दो उदाहरण begin अभिव्यक्तियों और हैंडलिंग फ़ंक्शन निकायों को संभालने में हैं। यह स्पष्ट रूप से एक बहुत ही आंशिक सूची है - आप lambda, let आदि के निकायों को भी चाहते हैं।लेकिन यह अभी भी कुछ अंधे मालिश से बेहतर है, क्योंकि यह केवल व्यावहारिक नहीं है क्योंकि आप वास्तव में पहले से ही नहीं बता सकते कि कोड का कुछ यादृच्छिक टुकड़ा कैसे समाप्त होगा। एक आसान उदाहरण के रूप में, इस सरल मैक्रो पर विचार करें:

    (define-syntax-rule (track E) 
        (begin (eprintf "Evaluating: ~s\n" 'E) 
         E)) 
    (x := 1) 
    
  5. इस का नतीजा यह है कि एक उचित समाधान के लिए, आप किसी तरह की जरूरत कोड पूर्व विस्तार करने के लिए इतना है कि आप तो यह स्कैन और के साथ सौदा कर सकते हैं आपके प्रत्यारोपण में कुछ ज्ञात मूल रूप हैं।

  6. हां, यह सब काम कर रहा है जो मैक्रो विस्तारक करता है, लेकिन चूंकि आप विस्तार कर रहे हैं कि विस्तार कैसे काम करता है, इसके आसपास कोई रास्ता नहीं है। (यह देखने के लिए कि यह एक मौलिक परिवर्तन क्यों है, (if := 1) जैसे कुछ पर विचार करें - क्या यह एक सशर्त अभिव्यक्ति या परिभाषा है? आप कैसे निर्णय लेते हैं कि किसके लिए प्राथमिकता है?) इस कारण से, इस तरह के "प्यारा वाक्यविन्यास" वाली भाषाओं के लिए, एक और लोकप्रिय दृष्टिकोण कोड को सादे एस-अभिव्यक्तियों में पढ़ने और पार्स करना है, और फिर वास्तविक भाषा कार्यान्वयन को सादा कार्य और मैक्रोज़ का उपयोग करने दें।

+0

हमम ... मैं देख सकता हूं कि मेरा प्रस्तावित समाधान बहुत बदसूरत कैसे हो सकता है ... अगर मैं पाठक-मैक्रो मार्ग पर जाने का फैसला करता हूं, तो क्या आप किसी अच्छे संसाधन के बारे में जानते हैं जहां मैं योजना (विशेष रूप से रैकेट) के बारे में जान सकता हूं -macros? मुझे उनके साथ बहुत कम अनुभव हुआ है, लेकिन मुझे याद है कि योजना पाठक-मैक्रोज़ मुझे सामान्य लिस्प पाठक-मैक्रोज़ कहने से बहुत कम शक्तिशाली लग रहा था। विशेष रूप से: क्या मैं एक नियमित मैक्रो लिख सकता हूं जो पाठक-मैक्रो परिभाषा तक फैलता है? या पढ़ना संशोधित करने के लिए उस बिंदु पर बहुत देर हो जाएगी? – Ord

+0

रैकेट में पूर्ण पार्सिंग (जो बहुत अधिक है) करने की क्षमता है, और सीएल-स्टाइल रीडटेबल-आधारित रीडर मैक्रोज़ (जो यहां भी एक अच्छा फिट नहीं है)। इसके बजाए, फ़ाइल को सामान्य रूप से सामान्य रूप से पढ़ने के लिए सबसे अच्छा है, फिर एस-एक्सप्रस ढूंढें जो आप चाहते हैं कि दिखें, और उन्हें ': = 'बाईं ओर ले जाकर परिवर्तित करें। लेकिन ऐसा करना संभव है कि केवल एक साधारण लूप बनाकर '#% मॉड्यूल-स्टार्ट 'चीज के साथ ऐसा ही हो और फिर परिणाम सामान्य को भेजता है - लेकिन यह लूप वास्तविक कोड के साथ किया जाना चाहिए, न कि 'वाक्य रचना-rules'। –

+0

ठीक है, इसलिए यदि मैं आपके समाधान को सही ढंग से समझता हूं - मैं नियमित रूप से 'परिभाषित-वाक्यविन्यास' मैक्रो का उपयोग अपने 'my-module-start' उदाहरण' की तरह करता हूं, और फिर मैं अपने मैक्रो में पारित होने वाले एस-एक्सप्रस के माध्यम से चलता हूं और उपसर्ग अभिव्यक्तियों में आवश्यकतानुसार उन्हें बदल दें? – Ord

3

define को फिर से परिभाषित करना थोड़ा जटिल है। @ एली के उत्कृष्ट स्पष्टीकरण देखें।

दूसरी तरफ, := के साथ set! का उपयोग करने के लिए आप कुछ सरल हैं।

#lang racket 

(module assignment racket 
    (provide (rename-out [app #%app])) 

    (define-syntax (app stx) 
    (syntax-case stx (:=) 
     [(_ id := expr) 
     (identifier? #'id) 
     (syntax/loc stx (set! id expr))]  
     [(_ . more) 
     (syntax/loc stx (#%app . more))]))) 

(require 'assignment) 

(define x 41) 
(x := (+ x 1)) 
(displayln x) 

एक एकल फाइल करने के लिए उदाहरण के रखने के लिए, मैं submodules (रैकेट का प्री-रिलीज़ संस्करण में उपलब्ध) का इस्तेमाल किया:

यहाँ एक छोटा सा उदाहरण है।

+0

धन्यवाद सोगार्ड; लेकिन मैं आपके समाधान को 'परिभाषित' करने के लिए भी क्यों लागू नहीं कर सका? यदि प्रत्येक अभिव्यक्ति को #% ऐप में स्पष्ट रूप से लपेटा गया है, तो क्या वह काम नहीं करेगा? – Ord

+0

संक्षेप में: परिभाषाएं अभिव्यक्ति नहीं हैं। परिभाषाएं और अभिव्यक्ति विभिन्न स्थानों पर हो सकती है। उदाहरण के लिए बाध्यकारी के दाईं ओर विचार करें। – soegaard

+0

तो, प्रत्येक 'परिभाषित' जैसी फ़ॉर्म को #% ऐप के साथ जरूरी नहीं है? या यह है कि कुछ रूप जहां परिभाषा उचित नहीं होगी #% ऐप के साथ लपेटा जाता है (जैसा कि, मुझे लगता है, आपका उदाहरण उदाहरण)? – Ord

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

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