The Scheme Programming Language, Third Edition [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

The Scheme Programming Language, Third Edition [Electronic resources] - نسخه متنی

Jean-Pierre Hbert, R. Kent Dybvig

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
توضیحات
افزودن یادداشت جدید





8.1. Keyword Bindings

This section describes forms that establish bindings between keywords and transformers. Keyword bindings may be established at top level, using define-syntax, or locally, using let-syntax, letrec-syntax, or internal define-syntax. Existing keyword bindings may be rebound temporarily with fluid-let-syntax.











(define-syntax keyword exp)


syntax


returns: unspecified


exp must evaluate to a transformer.

The following example defines let* as a syntactic extension, specifying the transformer with syntax-rules (see Section 8.2).


(define-syntax let*
(syntax-rules ()
(( () e1 e2 ...) (let () e1 e2 ...))
(( ((i1 v1) (i2 v2) ...) e1 e2 ...)
(let ((i1 v1))
(let* ((i2 v2) ...) e1 e2 ...)))))

define-syntax forms appearing at top level behave similarly to top-level variable definitions, and define-syntax forms appearing at the front of a lambda or other body behave similarly to internal variable definitions. That is, a binding established by a top-level define-syntax form is visible globally, whereas one established by an internal define-syntax form is visible only within the body in which the define-syntax form appears.

All bindings established by a set of internal definitions, whether keyword or variable definitions, are visible within the definitions themselves. For example, the expression


(let ()
(define even?
(lambda (x)
(or (= x 0) (odd? (- x 1)))))
(define-syntax odd?
(syntax-rules ()
(( x) (not (even? x)))))
(even? 10))

is valid and should return #t. It must be possible for the expander to determine the set of syntax and variable definitions that appears at the front of a body without referring to any of the locally defined identifiers. It is not legal, therefore, for an internal definition to affect the status of a (potential) internal definition in the same sequence of forms. For example,


(let ()
(define-syntax bind-to-zero
(syntax-rules ()
(( id) (define id 0))))
(bind-to-zero x)
x)

is not valid, since it would require the expander to expand (bind-to-zero x) in order to recognize it as a syntax definition. Rewritten as follows it returns 0.


(let ()
(define-syntax bind-to-zero
(syntax-rules ()
(( id) (define id 0))))
(let ()
(bind-to-zero x)
x))

A top-level syntactic definition must be established before its first use in order for that use to be recognized.














(let-syntax ((keyword exp) ...) form1 form2 ...)


syntax


(letrec-syntax ((keyword exp) ...) form1 form2 ...)


syntax


returns: see explanation


Each exp must evaluate to a transformer. For both let-syntax and letrec-syntax, each keyword is bound within the forms form1 form2 …. For letrec-syntax the binding scope also includes each exp.

A let-syntax or letrec-syntax form may expand into one or more expressions anywhere expressions are permitted, in which case the resulting expressions are treated as if enclosed in a begin expression. This allows a let-syntax or letrec-syntax form to expand into a definition or sequence of definitions anywhere definitions are permitted, in which case the definitions are treated as if they appeared in place of the let-syntax or letrec-syntax form. (This differs from the Revised5 Report treatment of these forms; see page 183.)

The following example highlights how let-syntax and letrec-syntax differ.


(let ((f (lambda (x) (+ x 1))))
(let-syntax ((f (syntax-rules ()
(( x) x)))
(g (syntax-rules ()
(( x) (f x)))))
(list (f 1) (g 1)))) ⇒ (1 2)
(let ((f (lambda (x) (+ x 1))))
(letrec-syntax ((f (syntax-rules ()
(( x) x)))
(g (syntax-rules ()
(( x) (f x)))))
(list (f 1) (g 1)))) ⇒ (1 1)

The two expressions are identical except that the let-syntax form in the first expression is a letrec-syntax form in the second. In the first expression, the f occurring in g refers to the let-bound variable f, whereas in the second it refers to the keyword f whose binding is established by the letrec-syntax form.











(fluid-let-syntax ((keyword exp) ...) form1 form2 ...)


syntax


returns: see explanation


Each exp must evaluate to a transformer. fluid-let-syntax is similar to let-syntax, except that instead of introducing new bindings for the keywords keyword …, fluid-let-syntax temporarily alters the existing bindings for the keywords during the expansion of its body. That is, during the expansion of form1 form2 …, the visible lexical (or top-level) binding for each keyword is temporarily replaced by a new association between the keyword and the corresponding transformer. This affects any references to the keyword that resolve to the same lexical (or top-level) binding whether the references occur in the text of the body or are introduced during its expansion. In contrast, let-syntax captures only those references that occur within the text of its body.

The following example shows how fluid-let-syntax differs from let-syntax.


(let ((f (lambda (x) (+ x 1))))
(let-syntax ((g (syntax-rules ()
(( x) (f x)))))
(let-syntax ((f (syntax-rules ()
(( x) x))))
(g 1)))) ⇒ 2
(let ((f (lambda (x) (+ x 1))))
(let-syntax ((g (syntax-rules ()
(( x) (f x)))))
(fluid-let-syntax ((f (syntax-rules ()
(( x) x))))
(g 1)))) ⇒ 1

The two expressions are identical except that the inner let-syntax form in the first expression is a fluid-let-syntax form in the second. In the first expression, the f occurring in the expansion of (g 1) refers to the let-bound variable f, whereas in the second it refers to the keyword f by virtue of the uid syntax binding for f.

/ 98