सिंटेक्स वस्तुओं अंतर्निहित रैकेट संकलक के लिए शाब्दिक संदर्भ के लिए भंडार हैं।
#lang racket/base
(* 3 4)
संकलक एक वाक्य रचना उद्देश्य यह है कि कार्यक्रम की संपूर्ण सामग्री का प्रतिनिधित्व प्राप्त करता है: वस्तुतः, जब हम कार्यक्रम की तरह दर्ज करें।
#lang racket/base
(define example-program
(open-input-string
"
#lang racket/base
(* 3 4)
"))
(read-accept-reader #t)
(define thingy (read-syntax 'the-test-program example-program))
(print thingy) (newline)
(syntax? thingy)
नोट कार्यक्रम में *
thingy
के भीतर एक वाक्य रचना वस्तु के रूप में एक संकलन समय प्रतिनिधित्व किया है कि: यहाँ हम देखते हैं कि वाक्य रचना वस्तु की तरह दिखता है क्या यह बताने के लिए एक उदाहरण है। यह अभी तक कोई बाध्यकारी जानकारी है: और पल में, thingy
में *
पता नहीं कहाँ से आता है। संकलन के दौरान विस्तार की प्रक्रिया के दौरान यह है कि संकलक *
#lang racket/base
के *
के संदर्भ के रूप में *
को संबद्ध करता है।
यदि हम संकलन समय पर चीजों के साथ बातचीत करते हैं तो हम इसे और अधिक आसानी से देख सकते हैं। (नोट: मैं जानबूझकर eval
के बारे में बात करने से परहेज कर रहा हूं क्योंकि मैं संकलन-समय बनाम रन-टाइम के दौरान क्या होता है, इस बारे में चर्चा को मिश्रित करना चाहता हूं।
#lang racket/base
(require (for-syntax racket/base))
;; This macro is only meant to let us see what the compiler is dealing with
;; at compile time.
(define-syntax (at-compile-time stx)
(syntax-case stx()
[(_ expr)
(let()
(define the-expr #'expr)
(printf "I see the expression is: ~s\n" the-expr)
;; Ultimately, as a macro, we must return back a rewrite of
;; the input. Let's just return the expr:
the-expr)]))
(at-compile-time (* 3 4))
हम यहाँ एक मैक्रो, at-compile-time
इस्तेमाल करेंगे, हमें संकलन के दौरान चीजों की राज्य निरीक्षण जाने के लिए:)
यहाँ हमें क्या इन वाक्यविन्यास वस्तुओं कर के और अधिक का निरीक्षण करने देने के लिए एक उदाहरण है। यदि आप इस कार्यक्रम को ड्रैकेट में चलाते हैं, तो आप देखेंगे कि ड्रैकेट पहले प्रोग्राम को संकलित करता है, और फिर इसे चलाता है। चूंकि यह प्रोग्राम संकलित करता है, जब यह at-compile-time
के उपयोग को देखता है, तो संकलक हमारे मैक्रो का आह्वान करेगा।
तो संकलन समय में, हम जैसे कुछ दिखाई देगा:
I see the expression is: #<syntax:20:17 (* 3 4)>
कार्यक्रम एक छोटा सा संशोधन करते हैं, और अगर हम पहचानकर्ता के identifier-binding
निरीक्षण कर सकते हैं देखें:
#lang racket/base
(require (for-syntax racket/base))
(define-syntax (at-compile-time stx)
(syntax-case stx()
[(_ expr)
(let()
(define the-expr #'expr)
(printf "I see the expression is: ~s\n" the-expr)
(when (identifier? the-expr)
(printf "The identifier binding is: ~s\n" (identifier-binding the-expr)))
the-expr)]))
((at-compile-time *) 3 4)
(let ([* +])
((at-compile-time *) 3 4))
I see the expression is: #<syntax:21:18 *>
The identifier binding is: (#<module-path-index> * #<module-path-index> * 0 0 0)
I see the expression is: #<syntax:24:20 *>
The identifier binding is: lexical
12
7
: हम DrRacket में इस कार्यक्रम चलाते हैं, तो हम निम्न उत्पादन देखेंगे (वैसे: हम आउटपुट को at-compile-time
से आगे क्यों देखते हैं? क्योंकि संकलन रनटाइम से पहले पूरी तरह से किया जाता है! कार्यक्रम अगर हम पहले से संकलन और raco make का उपयोग करके बाईटकोड बचाने के लिए, हम नहीं देखना होगा संकलक लागू किया जा रहा है जब हम कार्यक्रम चलाते हैं।)
समय संकलक at-compile-time
का उपयोग करता है तक पहुँच जाता है से, यह करने के लिए जानता है उपयुक्त व्याख्यात्मक बाध्यकारी जानकारी पहचानकर्ताओं को संबद्ध करें। जब हम पहली मामले में identifier-binding
का निरीक्षण किया, संकलक जानता है कि यह एक विशेष मॉड्यूल (इस मामले में, #lang racket/base
, जो कि module-path-index
व्यापार के बारे में है) से संबद्ध है,। लेकिन दूसरे मामले में, यह जानता है कि यह लेक्सिकल बाध्यकारी है: संकलक पहले से ही (let ([* +]) ...)
के माध्यम से चला गया है, और इसलिए यह जानता है कि *
का उपयोग let
द्वारा बाध्यकारी सेट पर वापस देखें।
रैकेट संकलक वाक्य रचना वस्तुओं का उपयोग करता है बंधन अपने मैक्रो के रूप में ग्राहकों को जानकारी, उस तरह का संवाद करने के लिए। वाक्य रचना वस्तुओं में बाध्यकारी जानकारी, प्रासंगिक नहीं हो सकता है क्योंकि समय से हम वाक्य रचना वस्तुओं का मूल्यांकन, उनके बाइंडिंग बातों का उल्लेख हो सकता है:
eval
उपयोग करने के लिए निरीक्षण करने के लिए सामान की इस तरह के मुद्दों से भरा है की कोशिश कर रहा वह अस्तित्व में नहीं है! यह मौलिक कारण है कि आप अपने प्रयोगों में त्रुटियों को देख रहे थे।
फिर भी, यहां एक उदाहरण है कि एस भाव और वाक्य रचना वस्तुओं के बीच अंतर पता चलता है:
#lang racket/base
(module mod1 racket/base
(provide x)
(define x #'(* 3 4)))
(module mod2 racket/base
(define * +) ;; Override!
(provide x)
(define x #'(* 3 4)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require (prefix-in m1: (submod "." mod1))
(prefix-in m2: (submod "." mod2)))
(displayln m1:x)
(displayln (syntax->datum m1:x))
(eval m1:x)
(displayln m2:x)
(displayln (syntax->datum m2:x))
(eval m2:x)
इस उदाहरण को ध्यान से इतना है कि वाक्य रचना वस्तुओं की सामग्री केवल करने के लिए मॉड्यूल बाध्य बातों का उल्लेख निर्माण किया है, जो उस समय मौजूद होगा जब हम eval
का उपयोग करेंगे। हम उदाहरण थोड़ा परिवर्तन हो, तो
(module broken-mod2 racket/base
(provide x)
(define x
(let ([* +])
#'(* 3 4))))
तो चीजें बुरी तरह तोड़ जब हम eval
x
कि broken-mod2
से बाहर आता है करने के लिए प्रयास करते हैं, के बाद से वाक्य रचना वस्तु एक शाब्दिक बाध्यकारी है कि द्वारा अस्तित्व में नहीं है बात कर रहा है समय हम eval
। eval
एक कठिन जानवर है।
क्या आपने देखा है: http://docs.racket-lang.org/reference/syntax-model.html#%28part._stxobj-model%29 अभी तक? – dyoo
@dyoo मैंने कई बार पढ़ा है और यही कारण है कि मुझे लगता है कि मैं उन्हें समझ गया, जब तक मैंने उपर्युक्त परीक्षणों की कोशिश नहीं की। उस पृष्ठ से, मैंने सोचा होगा कि '(eval (छाया-stx)) '''' वापस आना चाहिए। – Matt
बस स्पष्ट करने के लिए, जब आप सिंटैक्स ऑब्जेक्ट्स के बारे में पूछते हैं, तो यह वास्तव में एक विशिष्ट रैकेट चीज है: यह सामान्य रूप से एक योजना की बात नहीं है। सिंटैक्स ऑब्जेक्ट एक डेटा प्रकार है जो रैकेट के भाषा आधारभूत संरचना के केंद्र में है। – dyoo