reference-manual work
svn: r6480
This commit is contained in:
parent
d98743e1e9
commit
eeaa856ff1
|
@ -137,12 +137,14 @@
|
|||
|
||||
;; ----------------------------------------
|
||||
|
||||
(provide defproc defproc* defstruct defthing defform defform/none
|
||||
(provide defproc defproc* defstruct defthing defform defform* defform/none
|
||||
specsubform specsubform/inline
|
||||
var svar void-const)
|
||||
var svar void-const undefined-const)
|
||||
|
||||
(define (void-const)
|
||||
(schemefont "#<void>"))
|
||||
(define void-const
|
||||
(schemeresultfont "#<void>"))
|
||||
(define undefined-const
|
||||
(schemeresultfont "#<undefined>"))
|
||||
|
||||
(define dots0
|
||||
(make-element #f (list "...")))
|
||||
|
@ -161,9 +163,9 @@
|
|||
(syntax-rules ()
|
||||
[(_ name fields desc ...)
|
||||
(*defstruct 'name 'fields (lambda () (list desc ...)))]))
|
||||
(define-syntax (defform stx)
|
||||
(define-syntax (defform* stx)
|
||||
(syntax-case stx ()
|
||||
[(_ spec desc ...)
|
||||
[(_ [spec spec1 ...] desc ...)
|
||||
(with-syntax ([new-spec
|
||||
(syntax-case #'spec ()
|
||||
[(name . rest)
|
||||
|
@ -174,11 +176,17 @@
|
|||
#'name)
|
||||
#'rest)
|
||||
#'spec)])])
|
||||
#'(*defform #t 'spec (lambda (x) (schemeblock0 new-spec)) (lambda () (list desc ...))))]))
|
||||
#'(*defforms #t '(spec spec1 ...)
|
||||
(list (lambda (x) (schemeblock0 new-spec))
|
||||
(lambda (ignored) (schemeblock0 spec1)) ...)
|
||||
(lambda () (list desc ...))))]))
|
||||
(define-syntax (defform stx)
|
||||
(syntax-case stx ()
|
||||
[(_ spec desc ...) #'(defform* [spec] desc ...)]))
|
||||
(define-syntax (defform/none stx)
|
||||
(syntax-case stx ()
|
||||
[(_ spec desc ...)
|
||||
#'(*defform #f 'spec (lambda (ignored) (schemeblock0 spec)) (lambda () (list desc ...)))]))
|
||||
#'(*defforms #f '(spec) (list (lambda (ignored) (schemeblock0 spec))) (lambda () (list desc ...)))]))
|
||||
(define-syntax specsubform
|
||||
(syntax-rules ()
|
||||
[(_ spec desc ...)
|
||||
|
@ -383,35 +391,42 @@
|
|||
|
||||
(define (meta-symbol? s) (memq s '(... ...+ ?)))
|
||||
|
||||
(define (*defform kw? form form-proc content-thunk)
|
||||
(define (*defforms kw? forms form-procs content-thunk)
|
||||
(parameterize ([current-variable-list
|
||||
(let loop ([form (if kw? (cdr form) form)])
|
||||
(cond
|
||||
[(symbol? form) (if (meta-symbol? form)
|
||||
null
|
||||
(list form))]
|
||||
[(pair? form) (append (loop (car form))
|
||||
(loop (cdr form)))]
|
||||
[else null]))])
|
||||
(apply
|
||||
append
|
||||
(map (lambda (form)
|
||||
(let loop ([form (if kw? (cdr form) form)])
|
||||
(cond
|
||||
[(symbol? form) (if (meta-symbol? form)
|
||||
null
|
||||
(list form))]
|
||||
[(pair? form) (append (loop (car form))
|
||||
(loop (cdr form)))]
|
||||
[else null])))
|
||||
forms))])
|
||||
(make-splice
|
||||
(cons
|
||||
(make-table
|
||||
'boxed
|
||||
(list
|
||||
(list (make-flow
|
||||
(list
|
||||
((or form-proc
|
||||
(lambda (x)
|
||||
(make-paragraph
|
||||
(list
|
||||
(to-element
|
||||
`(,x
|
||||
. ,(cdr form)))))))
|
||||
(and kw?
|
||||
(make-target-element
|
||||
#f
|
||||
(list (to-element (car form)))
|
||||
(register-scheme-form-definition (car form))))))))))
|
||||
(map (lambda (form form-proc)
|
||||
(list
|
||||
(make-flow
|
||||
(list
|
||||
((or form-proc
|
||||
(lambda (x)
|
||||
(make-paragraph
|
||||
(list
|
||||
(to-element
|
||||
`(,x
|
||||
. ,(cdr form)))))))
|
||||
(and kw?
|
||||
(eq? form (car forms))
|
||||
(make-target-element
|
||||
#f
|
||||
(list (to-element (car form)))
|
||||
(register-scheme-form-definition (car form)))))))))
|
||||
forms form-procs))
|
||||
(content-thunk)))))
|
||||
|
||||
(define (*specsubform form form-thunk content-thunk)
|
||||
|
|
|
@ -28,19 +28,19 @@
|
|||
(define opt-color "schemeopt")
|
||||
|
||||
(define current-keyword-list
|
||||
(make-parameter '(define let let* letrec require provide let-values
|
||||
lambda new send if cond begin else and or
|
||||
(make-parameter '(define require provide
|
||||
new send if cond begin else and or
|
||||
define-syntax syntax-rules define-struct
|
||||
quote quasiquote unquote unquote-splicing
|
||||
syntax quasisyntax unsyntax unsyntax-splicing
|
||||
for/fold for/list for*/list for for/and for/or for* for*/or for*/and for*/fold
|
||||
for-values for*/list-values for/first for/last
|
||||
set!)))
|
||||
(define current-variable-list
|
||||
(make-parameter null))
|
||||
|
||||
(define defined-names (make-hash-table))
|
||||
|
||||
(define-struct (sized-element element) (length))
|
||||
|
||||
(define (typeset c multi-line? prefix1 prefix color?)
|
||||
(let* ([c (syntax-ize c 0)]
|
||||
[content null]
|
||||
|
@ -63,7 +63,10 @@
|
|||
(define out
|
||||
(case-lambda
|
||||
[(v cls)
|
||||
(out v cls (if (string? v) (string-length v) 1))]
|
||||
(out v cls (cond
|
||||
[(string? v) (string-length v)]
|
||||
[(sized-element? v) (sized-element-length v)]
|
||||
[else 1]))]
|
||||
[(v cls len)
|
||||
(unless (equal? v "")
|
||||
(if (equal? v "\n")
|
||||
|
@ -125,12 +128,13 @@
|
|||
(datum->syntax-object
|
||||
a
|
||||
(let ([val? (positive? quote-depth)])
|
||||
(make-element
|
||||
(make-sized-element
|
||||
(if val? value-color #f)
|
||||
(list
|
||||
(make-element (if val? value-color paren-color) '(". "))
|
||||
(typeset a #f "" "" (not val?))
|
||||
(make-element (if val? value-color paren-color) '(" .")))))
|
||||
(make-element (if val? value-color paren-color) '(" .")))
|
||||
(+ (syntax-span a) 4)))
|
||||
(list (syntax-source a)
|
||||
(syntax-line a)
|
||||
(- (syntax-column a) 2)
|
||||
|
@ -327,7 +331,7 @@
|
|||
(out (if (and (identifier? c)
|
||||
color?
|
||||
(quote-depth . <= . 0)
|
||||
(not (or it? is-kw? is-var?)))
|
||||
(not (or it? is-var?)))
|
||||
(make-delayed-element
|
||||
(lambda (renderer sec ht)
|
||||
(let* ([vtag (register-scheme-definition (syntax-e c))]
|
||||
|
|
|
@ -214,7 +214,7 @@ This pruning behavior of @scheme[#:when] is more useful with
|
|||
@scheme[for/list] than @scheme[for]. Whereas a plain @scheme[when]
|
||||
form normally suffices with @scheme[for], a @scheme[when] expression
|
||||
form in a @scheme[for/list] would cause the result list to contain
|
||||
@void-const[]s instead of omitting list elements.
|
||||
@|void-const|s instead of omitting list elements.
|
||||
|
||||
The @scheme[for*/list] is like @scheme[for*], nesting multiple
|
||||
iterations:
|
||||
|
|
|
@ -189,7 +189,7 @@ simpler (just a procedure call).
|
|||
We have ignored several other variants of the interation
|
||||
form---including plain @scheme[for], which is used when the iteration
|
||||
body is to be run only for its effect. For more complete information,
|
||||
see @secref["iterations+comprehensions"].
|
||||
see @secref["for"].
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{List Iteration from Scratch}
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
Some procedures or expression forms have no need for a result
|
||||
value. For example, the @scheme[display] procedure is called only for
|
||||
the side-effect of writing output. In such cases the reslt value is
|
||||
normally a special constant that prints as @void-const[]. When the
|
||||
result of an expression is simply @void-const[], the REPL does not
|
||||
normally a special constant that prints as @|void-const|. When the
|
||||
result of an expression is simply @|void-const|, the REPL does not
|
||||
print anything.
|
||||
|
||||
The @scheme[void] procedure takes any number of arguments and returns
|
||||
@void-const[]. (That is, the identifier @schemeidfont{void} is bound
|
||||
to a procedure that returns @void-const[], instead of being bound
|
||||
directly to @void-const[].)
|
||||
@|void-const|. (That is, the identifier @schemeidfont{void} is bound
|
||||
to a procedure that returns @|void-const|, instead of being bound
|
||||
directly to @|void-const|.)
|
||||
|
||||
@examples[
|
||||
(void)
|
||||
|
@ -23,16 +23,16 @@ directly to @void-const[].)
|
|||
(list (void))
|
||||
]
|
||||
|
||||
A constant that prints as @schemefont{#<undefined>} is used as the
|
||||
result of a reference to a local binding when the binding is not yet
|
||||
A constant that prints as @undefined-const is used as the result of a
|
||||
reference to a local binding when the binding is not yet
|
||||
initialized. Such early references are not possible for bindings that
|
||||
corerspond to procedure arguments, @scheme[let] bindings, or
|
||||
@scheme[let*] bindings; early reference requires a recursive binding
|
||||
context, such as @scheme[letrec] or local @scheme[define]s in a
|
||||
procedure body. Also, early references to top-level and module
|
||||
top-level bindings raise an exception, instead of producing
|
||||
@schemefont{#<undefined>}. For these reasons,
|
||||
@schemefont{#<undefined>} rarely appears.
|
||||
@|undefined-const|. For these reasons, @undefined-const rarely
|
||||
appears.
|
||||
|
||||
@def+int[
|
||||
(define (strange)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#reader(lib "docreader.ss" "scribble")
|
||||
@require["mz.ss"]
|
||||
|
||||
@title[#:style 'toc]{Built-In Datatypes}
|
||||
@title[#:style 'toc]{Core Datatypes and Procedures}
|
||||
|
||||
Each of the built-in datatypes comes with a set of procedures for
|
||||
manipulating members of the datatype.
|
||||
|
@ -196,10 +196,10 @@ If the @scheme[lst]s are empty, then @scheme[#f] is returned.}
|
|||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "void"]{Void and Undefined}
|
||||
|
||||
@defproc[(void [v any/c] ...) void?]{Returns the constant @void-const[]. Each
|
||||
@defproc[(void [v any/c] ...) void?]{Returns the constant @|void-const|. Each
|
||||
@scheme[v] argument is ignored.}
|
||||
|
||||
@defproc[(void? [v any/c]) void?]{Returns @scheme[#t] if @scheme[v] is the
|
||||
constant @void-const[], @scheme[#f] otherwise.}
|
||||
constant @|void-const|, @scheme[#f] otherwise.}
|
||||
|
||||
|
||||
|
|
250
collects/scribblings/reference/derived.scrbl
Normal file
250
collects/scribblings/reference/derived.scrbl
Normal file
|
@ -0,0 +1,250 @@
|
|||
#reader(lib "docreader.ss" "scribble")
|
||||
@require["mz.ss"]
|
||||
|
||||
@title[#:tag "mz:derived-syntax"]{Derived Syntactic Forms}
|
||||
|
||||
@section{Iterations and Comprehensions: @scheme[for], @scheme[for/list], ...}
|
||||
|
||||
@defform[(for (for-clause ...) . body)]{
|
||||
|
||||
Iteratively evaluates @scheme[body]. The @scheme[for-clause]s
|
||||
introduce bindings whose scope inculdes @scheme[body] and that
|
||||
determine the number of times that @scheme[body] is evaluated.
|
||||
|
||||
In the simple case, each @scheme[for-clause] has the form
|
||||
|
||||
@specsubform[[id seq-expr]]{}
|
||||
|
||||
In this case, the @scheme[_seq-expr]s are evaluated left-to-right, and
|
||||
each must produce a sequence value (see @secref["mz:sequences"]). The
|
||||
@scheme[for] form iterates by drawing an element from each sequence;
|
||||
if any sequence is empty, then the iteration stops, and @|void-const|
|
||||
is the result of the @scheme[for] expression. Otherwise a location is
|
||||
created for each @scheme[_id] to hold the corresponding element. The
|
||||
@scheme[_id]s are then bound in the @scheme[body], which is evaluated,
|
||||
and whose result(s) is(are) ignored. Iteration continues with the next
|
||||
element in each sequence and with fresh locations for each
|
||||
@scheme[_id]. Zero @scheme[for-clause]s is equivalent to a single
|
||||
@scheme[for-clause] that binds an unreferenced @scheme[_id] to a
|
||||
sequence containing one element. All of the @scheme[_id]s must be
|
||||
distinct according to @scheme[bound-identifier=?].
|
||||
|
||||
If any @scheme[for-clause] has the form
|
||||
|
||||
@specsubform[(code:line #:when guard-expr)]{}
|
||||
|
||||
then only the preceding clauses (containing no @scheme[#:when])
|
||||
determine iteration as above, and the @scheme[body] is effectively
|
||||
wrapped as
|
||||
|
||||
@schemeblock[
|
||||
(when guard-expr
|
||||
(for (for-clause ...) . body))
|
||||
]
|
||||
|
||||
using the remaining @scheme[for-clauses].
|
||||
|
||||
@examples[
|
||||
(for ([i '(1 2 3)]
|
||||
[j "abc"]
|
||||
#:when (odd? i)
|
||||
[k #2(#t #f)])
|
||||
(display (list i j k)))
|
||||
(for ()
|
||||
(display "here"))
|
||||
(for ([i '()])
|
||||
(error "doesn't get here"))
|
||||
]}
|
||||
|
||||
@defform[(for/list (for-clause ...) . body)]{ Iterates like
|
||||
@scheme[for], but that the last expression of @scheme[body] must
|
||||
produce a single value, and the result of the @scheme[for/list]
|
||||
expression is a list of the results in order.
|
||||
|
||||
@examples[
|
||||
(for/list ([i '(1 2 3)]
|
||||
[j "abc"]
|
||||
#:when (odd? i)
|
||||
[k #2(#t #f)])
|
||||
(list i j k))
|
||||
(for/list () 'any)
|
||||
(for/list ([i '()])
|
||||
(error "doesn't get here"))
|
||||
]}
|
||||
|
||||
@defform[(for/and (for-clause ...) . body)]{ Iterates like
|
||||
@scheme[for], but when last expression of @scheme[body] produces
|
||||
@scheme[#f], then iteration terminates, and the result of the
|
||||
@scheme[for/and] expression is @scheme[#f]. If the @scheme[body]
|
||||
is never evaluated, then the result of the @scheme[for/and]
|
||||
expression is @scheme[#t]. Otherwise, the result is the (single)
|
||||
result from the last evaluation of @scheme[body].
|
||||
|
||||
@examples[
|
||||
(for/and ([i '(1 2 3 "x")])
|
||||
(i . < . 3))
|
||||
(for/and ([i '(1 2 3 4)])
|
||||
i)
|
||||
(for/and ([i '()])
|
||||
(error "doesn't get here"))
|
||||
]}
|
||||
|
||||
@defform[(for/or (for-clause ...) . body)]{ Iterates like
|
||||
@scheme[for], but when last expression of @scheme[body] produces
|
||||
a value other than @scheme[#f], then iteration terminates, and
|
||||
the result of the @scheme[for/or] expression is the same
|
||||
(single) value. If the @scheme[body] is never evaluated, then the
|
||||
result of the @scheme[for/or] expression is
|
||||
@scheme[#f]. Otherwise, the result is @scheme[#f].
|
||||
|
||||
@examples[
|
||||
(for/or ([i '(1 2 3 "x")])
|
||||
(i . < . 3))
|
||||
(for/or ([i '(1 2 3 4)])
|
||||
i)
|
||||
(for/or ([i '()])
|
||||
(error "doesn't get here"))
|
||||
]}
|
||||
|
||||
@defform[(for/first (for-clause ...) . body)]{ Iterates like
|
||||
@scheme[for], but after @scheme[body] is evaluated the first
|
||||
time, then the iteration terminates, and the @scheme[for/first]
|
||||
result is the (single) result of @scheme[body]. If the
|
||||
@scheme[body] is never evaluated, then the result of the
|
||||
@scheme[for/first] expression is @scheme[#f].
|
||||
|
||||
@examples[
|
||||
(for/first ([i '(1 2 3 "x")]
|
||||
#:when (even? i))
|
||||
(number->string i))
|
||||
(for/first ([i '()])
|
||||
(error "doesn't get here"))
|
||||
]}
|
||||
|
||||
@defform[(for/last (for-clause ...) . body)]{ Iterates like
|
||||
@scheme[for], but the @scheme[for/last] result is the (single)
|
||||
result of of the last evaluation of @scheme[body]. If the
|
||||
@scheme[body] is never evaluated, then the result of the
|
||||
@scheme[for/last] expression is @scheme[#f].
|
||||
|
||||
@examples[
|
||||
(for/last ([i '(1 2 3 4 5)]
|
||||
#:when (even? i))
|
||||
(number->string i))
|
||||
(for/last ([i '()])
|
||||
(error "doesn't get here"))
|
||||
]}
|
||||
|
||||
@defform[(for/fold ([accum-id init-expr] ...) (for-clause ...). body)]{
|
||||
|
||||
Iterates like @scheme[for]. Before iteration starts, the
|
||||
@scheme[init-expr]s are evaluated to produce initial accumulator
|
||||
values. At the start of each out iteration, a location is generated
|
||||
for each @scheme[accum-id], and the correspinding current accumulator
|
||||
value is placed into the location. The last expression in
|
||||
@scheme[body] must produce as many values as @scheme[accum-id]s, and
|
||||
those values become the current accumulator values. When iteration
|
||||
terminates, the result of the @scheme[fold/for] expression is(are) the
|
||||
accumulator value(s).
|
||||
|
||||
@examples[
|
||||
(for/fold ([sum 0]
|
||||
[rev-roots null])
|
||||
([i '(1 2 3 4)])
|
||||
(values (+ sum i) (cons (sqrt i) rev-roots)))
|
||||
]}
|
||||
|
||||
@defform[(for* (for-clause ...) . body)]{
|
||||
Like @scheme[for], but with an implicit @scheme[#:when #t] between
|
||||
each pair of @scheme[for-clauses], so that all sequence iterations are
|
||||
nested.
|
||||
|
||||
@examples[
|
||||
(for* ([i '(1 2)]
|
||||
[j "ab"])
|
||||
(display (list i j)))
|
||||
]}
|
||||
|
||||
@defform[(for*/list (for-clause ...) . body)]{
|
||||
Like @scheme[for/list], but with the implicit nesting of @scheme[for*].
|
||||
@examples[
|
||||
(for*/list ([i '(1 2)]
|
||||
[j "ab"])
|
||||
(list i j))
|
||||
]}
|
||||
|
||||
@defform[(for*/and (for-clause ...) . body)]{
|
||||
Like @scheme[for/and], but with the implicit nesting of @scheme[for*].}
|
||||
|
||||
@defform[(for*/or (for-clause ...) . body)]{
|
||||
Like @scheme[for/or], but with the implicit nesting of @scheme[for*].}
|
||||
|
||||
@defform[(for*/first (for-clause ...) . body)]{
|
||||
Like @scheme[for/first], but with the implicit nesting of @scheme[for*].}
|
||||
|
||||
@defform[(for*/last (for-clause ...) . body)]{
|
||||
Like @scheme[for/last], but with the implicit nesting of @scheme[for*].}
|
||||
|
||||
@defform[(for*/fold ([accum-id init-expr] ...) (for-clause ...) . body)]{
|
||||
Like @scheme[for/fold], but with the implicit nesting of @scheme[for*].}
|
||||
|
||||
@defform[(for-values (for-values-clause ...) . body)]{ Like
|
||||
@scheme[for], but each @scheme[for-values-clause] has one of the
|
||||
following two forms:
|
||||
|
||||
@specsubform[[(id ...) seq-expr]]{ The sequence produced by
|
||||
@scheme[_seq-expr] must return as many values for each iteration as
|
||||
@scheme[id]s, and the values are placed in the locations generated
|
||||
for the @scheme[id]s.}
|
||||
|
||||
@specsubform[(code:line #:when guard-expr)]{As in @scheme[for].}
|
||||
|
||||
@examples[
|
||||
(for-values ([(i j) #hash(("a" . 1) ("b" . 20))])
|
||||
(display (list i j)))
|
||||
]}
|
||||
|
||||
@defform[(for/list-values (for-values-clause ...) . body)]{ Like
|
||||
@scheme[for/list], but with multiple-value clauses like
|
||||
@scheme[for-values].}
|
||||
|
||||
@defform[(for/and-values (for-values-clause ...) . body)]{ Like
|
||||
@scheme[for-and], but with multiple-value clauses like
|
||||
@scheme[for-values].}
|
||||
|
||||
@defform[(for/or-values (for-values-clause ...) . body)]{ Like
|
||||
@scheme[for/or], but with multiple-value clauses like
|
||||
@scheme[for-values].}
|
||||
|
||||
@defform[(for/first-values (for-values-clause ...) . body)]{ Like
|
||||
@scheme[for/first], but with multiple-value clauses like
|
||||
@scheme[for-values].}
|
||||
|
||||
@defform[(for/last-values (for-values-clause ...) . body)]{ Like
|
||||
@scheme[for/last], but with multiple-value clauses like
|
||||
@scheme[for-values].}
|
||||
|
||||
@defform[(for/fold-values ([id expr] ...) (for-values-clause ...) . body)]{ Like
|
||||
@scheme[for/fold], but with multiple-value clauses like
|
||||
@scheme[for-values].}
|
||||
|
||||
@defform[(for*-values (for-values-clause ...) . body)]{
|
||||
Like @scheme[for-values], but with the implicit nesting of @scheme[for*].}
|
||||
|
||||
@defform[(for*/list-values (for-values-clause ...) . body)]{
|
||||
Like @scheme[for/list-values], but with the implicit nesting of @scheme[for*].}
|
||||
|
||||
@defform[(for*/and-values (for-values-clause ...) . body)]{
|
||||
Like @scheme[for/and-values], but with the implicit nesting of @scheme[for*].}
|
||||
|
||||
@defform[(for*/or-values (for-values-clause ...) . body)]{
|
||||
Like @scheme[for/or-values], but with the implicit nesting of @scheme[for*].}
|
||||
|
||||
@defform[(for*/first-values (for-values-clause ...) . body)]{
|
||||
Like @scheme[for/first-values], but with the implicit nesting of @scheme[for*].}
|
||||
|
||||
@defform[(for*/last-values (for-values-clause ...) . body)]{
|
||||
Like @scheme[for/last-values], but with the implicit nesting of @scheme[for*].}
|
||||
|
||||
@defform[(for*/fold-values ([id expr] ...) (for-values-clause ...) . body)]{
|
||||
Like @scheme[for/fold-values], but with the implicit nesting of @scheme[for*].}
|
|
@ -177,7 +177,7 @@ right-hand expression must be reduced to a value.
|
|||
[{}
|
||||
(begin (code:hilite (define x 10)) (+ x 1))]
|
||||
[{(define x 10)}
|
||||
(code:hilite (begin #,(void-const) (+ x 1)))]
|
||||
(code:hilite (begin #,void-const (+ x 1)))]
|
||||
[{(define x 10)}
|
||||
(+ (code:hilite x) 1)]
|
||||
[{(define x 10)}
|
||||
|
@ -197,7 +197,7 @@ existing top-level binding:
|
|||
[{(define x 10)}
|
||||
(begin (code:hilite (set! x 8)) x)]
|
||||
[{(define x 8)}
|
||||
(code:hilite (begin #,(void-const) x))]
|
||||
(code:hilite (begin #,void-const x))]
|
||||
[{(define x 8)}
|
||||
(code:hilite x)]
|
||||
[{(define x 8)}
|
||||
|
@ -217,7 +217,7 @@ values, which are the results of expressions, and @defterm{objects},
|
|||
which hold the data referenced by a value.
|
||||
|
||||
A few kinds of objects can serve directly as values, including
|
||||
booleans, @void-const[], and small exact integers. More generally,
|
||||
booleans, @|void-const|, and small exact integers. More generally,
|
||||
however, a value is a reference to an object. For example, a value can
|
||||
be a reference to a particular vector that currently holds the value
|
||||
@scheme[10] in its first slot. If an object is modified, then the
|
||||
|
@ -243,7 +243,7 @@ create objects, such as @scheme[vector], add to the set of objects:
|
|||
(vector-ref y 0))]
|
||||
[{(define <o1> #(10 20))}
|
||||
{(define x <o1>)}
|
||||
(code:hilite (begin #,(void-const)
|
||||
(code:hilite (begin #,void-const
|
||||
(define y x)
|
||||
(vector-set! x 0 11)
|
||||
(vector-ref y 0)))]
|
||||
|
@ -260,7 +260,7 @@ create objects, such as @scheme[vector], add to the set of objects:
|
|||
[{(define <o1> #(10 20))}
|
||||
{(define x <o1>)
|
||||
(define y <o1>)}
|
||||
(code:hilite (begin #,(void-const)
|
||||
(code:hilite (begin #,void-const
|
||||
(vector-set! x 0 11)
|
||||
(vector-ref y 0)))]
|
||||
[{(define <o1> #(10 20))}
|
||||
|
@ -276,7 +276,7 @@ create objects, such as @scheme[vector], add to the set of objects:
|
|||
[{(define <o1> #(11 20))}
|
||||
{(define x <o1>)
|
||||
(define y <o1>)}
|
||||
(code:hilite (begin #,(void-const)
|
||||
(code:hilite (begin #,void-const
|
||||
(vector-ref y 0)))]
|
||||
[{(define <o1> #(11 20))}
|
||||
{(define x <o1>)
|
||||
|
@ -432,7 +432,7 @@ the variable is always replaced with a location by the time the
|
|||
[{(define <p1> (lambda (x) (begin (set! x 3) x)))}
|
||||
{(define f <p1>)
|
||||
(define xloc 3)}
|
||||
(code:hilite (begin #,(void-const) xloc))]
|
||||
(code:hilite (begin #,void-const xloc))]
|
||||
[{(define <p1> (lambda (x) (begin (set! x 3) x)))}
|
||||
{(define f <p1>)
|
||||
(define xloc 3)}
|
||||
|
|
|
@ -388,7 +388,7 @@ noted above). Two numbers are @scheme[equal?] when they are
|
|||
|
||||
|
||||
@; ------------------------------------------------------------------------
|
||||
@section{Trigonometric Functions}
|
||||
@section{Trignometric Functions}
|
||||
|
||||
@defproc[(sin [z number?]) number?]{ Returns the sine of @scheme[z], where
|
||||
@scheme[z] is in radians.
|
||||
|
|
|
@ -15,6 +15,7 @@ language.
|
|||
@include-section["read.scrbl"]
|
||||
@include-section["macros.scrbl"]
|
||||
@include-section["syntax.scrbl"]
|
||||
@include-section["derived.scrbl"]
|
||||
@include-section["data.scrbl"]
|
||||
|
||||
@index-section["mzscheme-index"]
|
||||
|
|
|
@ -1,11 +1,23 @@
|
|||
#reader(lib "docreader.ss" "scribble")
|
||||
@require["mz.ss"]
|
||||
|
||||
@title[#:tag "mz:syntax"]{Core Syntactic Forms}
|
||||
@title[#:tag "mz:syntax" #:style 'toc]{Core Syntactic Forms}
|
||||
|
||||
A syntactic form is described by a BNF-like notation that describes a
|
||||
combination of (syntax-wrapped) pairs, symbols, and other data (not a
|
||||
sequence of characters):
|
||||
This section describes core syntax forms that apear in a fully
|
||||
expanded expression, plus a few closely-related non-core forms.
|
||||
|
||||
@local-table-of-contents[]
|
||||
|
||||
@subsubsub*section{Notation}
|
||||
|
||||
Each syntactic form is described by a BNF-like notation that describes
|
||||
a combination of (syntax-wrapped) pairs, symbols, and other data (not
|
||||
a sequence of characters). These grammatical specifications are shown
|
||||
as follows:
|
||||
|
||||
@specsubform[(#, @schemekeywordfont{some-form} id ...)]
|
||||
|
||||
Within such specifications,
|
||||
|
||||
@itemize{
|
||||
|
||||
|
@ -18,61 +30,86 @@ sequence of characters):
|
|||
@item{@scheme[?] means zero instances or one instance
|
||||
of the preceding datum.}
|
||||
|
||||
@item{Italic sequences of characters play the role of non-terminals. In
|
||||
particular:
|
||||
@item{italic meta-identifier play the role of non-terminals; in
|
||||
particular,
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{A sequence that ends in @scheme[_id] refers to a
|
||||
@item{a meta-identifier that ends in @scheme[_id] stands for a
|
||||
syntax-wrapped symbol.}
|
||||
|
||||
@item{A sequence that ends in @scheme[_keyword] refers to a
|
||||
syntax-wrapped keyword.}
|
||||
@item{a meta-identifier that ends in @scheme[_keyword] stands
|
||||
for a syntax-wrapped keyword.}
|
||||
|
||||
@item{A sequence that end with @scheme[_expr] refers to a sub-form
|
||||
that is expanded as an expression.}
|
||||
}}
|
||||
}
|
||||
@item{a meta-identifier that ends with @scheme[_expr] stands
|
||||
for a sub-form that is expanded as an expression.}
|
||||
|
||||
@item{a meta-identifier that ends with @scheme[_body] stands
|
||||
for a non-empty syntax-wrapped list of sub-forms; the
|
||||
list is expanded as internal-definition sequence
|
||||
followed by at least one expression (see
|
||||
@secref["intdef-body"] for details).}
|
||||
|
||||
}} }
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Variable Reference}
|
||||
@section{Variable References and @scheme[#%top]}
|
||||
|
||||
@defform/none[id]{
|
||||
|
||||
A reference to a module-level or local binding, when @scheme[id] is
|
||||
Refers to a module-level or local binding, when @scheme[id] is
|
||||
not bound as a transformer (see @secref["mz:expansion"]). At run-time,
|
||||
the reference evaluates to the value in the location associated with
|
||||
the binding.
|
||||
|
||||
When the expander encounters an @scheme[id] that is not bound by a
|
||||
module or local binding, it converts the expression to @scheme[(#%top
|
||||
. id)].}
|
||||
module or local binding, it converts the expression to @scheme[(#,
|
||||
@schemeidfont{#%top} . id)] giving @schemeidfont{#%top} the lexical
|
||||
context of the @scheme[id]; typically, that context refers to
|
||||
@scheme[#%top].
|
||||
|
||||
@examples[
|
||||
(define x 10)
|
||||
x
|
||||
(let ([x 5]) x)
|
||||
((lambda (x) x) 2)
|
||||
]}
|
||||
|
||||
@defform[(#%top . id)]{
|
||||
|
||||
A reference to a top-level definition that could bind @scheme[id],
|
||||
Refers to a top-level definition that could bind @scheme[id],
|
||||
even if @scheme[id] has a local binding in its context. Such
|
||||
references are disallowed anywhere within a @scheme[module] form.}
|
||||
references are disallowed anywhere within a @scheme[module] form.
|
||||
|
||||
@examples[
|
||||
(define x 12)
|
||||
(let ([x 5]) (#%top . x))
|
||||
]}
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Procedure Application}
|
||||
@section{Procedure Applications and @scheme[#%app]}
|
||||
|
||||
@defform/none[(proc-expr arg ...)]{
|
||||
|
||||
A procedure application, normally, when @scheme[proc-expr] is not an
|
||||
Applies a procedure, normally, when @scheme[proc-expr] is not an
|
||||
identifier that has a transformer binding (see
|
||||
@secref["mz:expansion"]).
|
||||
|
||||
More precisely, the expander converts this form to @scheme[(#,
|
||||
@schemeidfont{#%app} proc-expr arg ...)] using the lexical
|
||||
context for @schemeidfont{#%app} that is associated with the original
|
||||
form (i.e., the pair that combines @scheme[proc-expr] and its
|
||||
@schemeidfont{#%app} proc-expr arg ...)], giving @schemeidfont{#%app}
|
||||
the lexical context that is associated with the original form (i.e.,
|
||||
the pair that combines @scheme[proc-expr] and its
|
||||
arguments). Typically, the lexical context of the pair indicates the
|
||||
procedure-application @scheme[#%app] that is described next.}
|
||||
procedure-application @scheme[#%app] that is described next.
|
||||
|
||||
@examples[
|
||||
(+ 1 2)
|
||||
((lambda (x #:arg y) (list y x)) #:arg 2 1)
|
||||
]}
|
||||
|
||||
@defform[(#%app proc-expr arg ...)]{
|
||||
|
||||
A procedure application. Each @scheme[arg] is one of the following:
|
||||
Applies a procedure. Each @scheme[arg] is one of the following:
|
||||
|
||||
@specsubform[arg-expr]{The resulting value is a non-keyword
|
||||
argument.}
|
||||
|
@ -85,7 +122,7 @@ The @scheme[proc-expr] and @scheme[_arg-expr]s are evaluated in order,
|
|||
left to right. If the result of @scheme[proc-expr] is a procedure that
|
||||
accepts as many arguments as non-@scheme[_keyword]
|
||||
@scheme[_arg-expr]s, if it accepts arguments for all of the
|
||||
e@scheme[_keyword]s in the application, and if all required
|
||||
@scheme[_keyword]s in the application, and if all required
|
||||
keyword-based arguments are represented among the @scheme[_keyword]s
|
||||
in the application, then the procedure is called with the values of
|
||||
the @scheme[arg-expr]s. Otherwise, the @exnraise[exn:fail:contract].
|
||||
|
@ -96,20 +133,26 @@ expression is(are) the result(s) of the procedure.
|
|||
|
||||
The relative order of @scheme[_keyword]-based arguments matters only
|
||||
for the order of @scheme[_arg-expr] evaluations; the arguments are
|
||||
regonized by the applied procedure based on the @scheme[_keyword], and
|
||||
not their positions. The other @scheme[_arg-expr] values, in contrast,
|
||||
are recognized by the applied procedure according to their order in
|
||||
the application form.}
|
||||
associated with argument variables in the applied procedure based on
|
||||
the @scheme[_keyword]s, and not their positions. The other
|
||||
@scheme[_arg-expr] values, in contrast, are associated with variables
|
||||
according to their order in the application form.
|
||||
|
||||
@examples[
|
||||
(#%app + 1 2)
|
||||
(#%app (lambda (x #:arg y) (list y x)) #:arg 2 1)
|
||||
(#%app cons)
|
||||
]}
|
||||
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Procedure Expression: @scheme[lambda] and @scheme[case-lambda]}
|
||||
@section{Procedure Expressions: @scheme[lambda] and @scheme[case-lambda]}
|
||||
|
||||
@defform[(lambda formals* body-expr ...+)]{
|
||||
@defform[(lambda formals* . body)]{
|
||||
|
||||
An expression that procedures a procedure. The @scheme[formals*]
|
||||
determines the number of arguments that the procedure accepts. It is
|
||||
either a simple @scheme[_formals], or one of the extended forms.
|
||||
Procedures a procedure. The @scheme[formals*] determines the number of
|
||||
arguments that the procedure accepts. It is either a simple
|
||||
@scheme[_formals], or one of the extended forms.
|
||||
|
||||
A simple @scheme[_formals] has one of the following three forms:
|
||||
|
||||
|
@ -128,11 +171,11 @@ A simple @scheme[_formals] has one of the following three forms:
|
|||
arguments. All arguments are placed into a list that is
|
||||
associated with @scheme[rest-id].}
|
||||
|
||||
In addition to the form of a @scheme[_formals], a @scheme[formals*]
|
||||
can be a sequence of @scheme[_formal*]s optionally ending with a
|
||||
Besides the three @scheme[_formals] forms, a @scheme[formals*] can be
|
||||
a sequence of @scheme[_formal-arg]s optionally ending with a
|
||||
@scheme[rest-id]:
|
||||
|
||||
@specsubform[(formal* ...)]{ Each @scheme[formal*] has the following
|
||||
@specsubform[(formal-arg ...)]{ Each @scheme[formal-arg] has the following
|
||||
four forms:
|
||||
|
||||
@specsubform[id]{Adds one to both the minimum and maximum
|
||||
|
@ -145,7 +188,7 @@ can be a sequence of @scheme[_formal*]s optionally ending with a
|
|||
@scheme[id] is associated with an actual argument by position,
|
||||
and if no such argument is provided, the @scheme[default-expr]
|
||||
is evaluated to produce a value associated with @scheme[id].
|
||||
No @scheme[formal*] with a @scheme[default-expr] can appear
|
||||
No @scheme[formal-arg] with a @scheme[default-expr] can appear
|
||||
before an @scheme[id] without a @scheme[default-expr] and
|
||||
without a @scheme[keyword].}
|
||||
|
||||
|
@ -161,25 +204,26 @@ can be a sequence of @scheme[_formal*]s optionally ending with a
|
|||
otherwise, the @scheme[default-expr] is evaluated to obtain a
|
||||
value to associate with @scheme[id].}
|
||||
|
||||
The position of a @scheme[_keyword] @scheme[formal*] in
|
||||
The position of a @scheme[_keyword] @scheme[formal-arg] in
|
||||
@scheme[formals*] does not matter, but each specified
|
||||
@scheme[_keyword] must be distinct.}
|
||||
|
||||
@specsubform[(formal* ...+ . rest-id)]{ Like the previous case, but
|
||||
@specsubform[(formal-arg ...+ . rest-id)]{ Like the previous case, but
|
||||
the procedure accepts any number of non-keyword arguments
|
||||
beyond its minimum number of arguments. When more arguments are
|
||||
provided than non-@scheme[_keyword] arguments among the @scheme[formal*]s,
|
||||
the extra arguments are placed into a list that is associated to
|
||||
@scheme[rest-id].}
|
||||
beyond its minimum number of arguments. When more arguments are
|
||||
provided than non-@scheme[_keyword] arguments among the
|
||||
@scheme[formal-arg]s, the extra arguments are placed into a
|
||||
list that is associated to @scheme[rest-id].}
|
||||
|
||||
The @scheme[formals*] identifiers are bound in the
|
||||
@scheme[body-expr]s. When the procedure is applied, a new location is
|
||||
created for each identifier, and the location is filled with the
|
||||
associated argument value.
|
||||
The @scheme[formals*] identifiers are bound in the @scheme[body]. (See
|
||||
@secref["intdef-body"] for information on @scheme[body] forms.) When
|
||||
the procedure is applied, a new location is created for each
|
||||
identifier, and the location is filled with the associated argument
|
||||
value.
|
||||
|
||||
If any identifier appears in @scheme[body-expr]s that is not one of
|
||||
the identifiers in @scheme[formals*], then it refers to the same
|
||||
location that it would if it appears in place of the @scheme[lambda]
|
||||
If any identifier appears in @scheme[body] that is not one of the
|
||||
identifiers in @scheme[formals*], then it refers to the same location
|
||||
that it would if it appeared in place of the @scheme[lambda]
|
||||
expression. (In other words, variable reference is lexically scoped.)
|
||||
|
||||
When multiple identifiers appear in a @scheme[formals*], they must be
|
||||
|
@ -189,14 +233,25 @@ If the procedure procedure by @scheme[lambda] is applied to fewer or
|
|||
more arguments than it accepts, the @exnraise[exn:fail:contract]. If
|
||||
@scheme[formals*] includes @scheme[keyword]s and an application
|
||||
includes too few arguments before the keyword section, the same
|
||||
keyword in multiple odd positions of the keyword section, or a keyword
|
||||
that is not among the @scheme[formals*] @scheme[keyword]s in an odd
|
||||
position of the keyword section, then the
|
||||
@exnraise[exn:fail:contract].}
|
||||
keyword in multiple positions, or a keyword that is not among the
|
||||
@scheme[formals*] @scheme[_keyword]s, then the
|
||||
@exnraise[exn:fail:contract].
|
||||
|
||||
@defform[(case-lambda [formals body-expr ...+] ...)]{
|
||||
The last expression in @scheme[body] is in tail position with respect
|
||||
to the procedure body.
|
||||
|
||||
An expression that procedure. Each @scheme[[forms body-expr ...+]]
|
||||
@examples[
|
||||
((lambda (x) x) 10)
|
||||
((lambda (x y) (list y x)) 1 2)
|
||||
((lambda (x [y 5]) (list y x)) 1 2)
|
||||
(let ([f (lambda (x #:arg y) (list y x))])
|
||||
(list (f 1 #:arg 2)
|
||||
(f #:arg 2 1)))
|
||||
]}
|
||||
|
||||
@defform[(case-lambda [formals . body] ...)]{
|
||||
|
||||
Produces a procedure. Each @scheme[[forms body]]
|
||||
clause is analogous to a single @scheme[lambda] procedure; applying
|
||||
the @scheme[case-lambda]-generated procedure is the same as applying a
|
||||
procedure that corresponds to one of the clauses---the first procedure
|
||||
|
@ -207,4 +262,126 @@ procedure accepts the given number of arguments, the
|
|||
Note that a @scheme[case-lambda] clause supports only
|
||||
@scheme[formals], not the more general @scheme[_formals*] of
|
||||
@scheme[lambda]. That is, @scheme[case-lambda] does not directly
|
||||
support keyword and optional arguments for an inidvidual clause.}
|
||||
support keyword and optional arguments.
|
||||
|
||||
@examples[
|
||||
(let ([f (case-lambda
|
||||
[() 10]
|
||||
[(x) x]
|
||||
[(x y) (list y x)]
|
||||
[r r])])
|
||||
(list (f)
|
||||
(f 1)
|
||||
(f 1 2)
|
||||
(f 1 2 3)))
|
||||
]}
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Local Binding: @scheme[let], @scheme[let*], and @scheme[letrec]}
|
||||
|
||||
@defform*[[(let ([id val-expr] ...) . body)
|
||||
(let proc-id ([id init-expr] ...) . body)]]{
|
||||
|
||||
The first form evaluates the @scheme[val-expr]s left-to-right, creates
|
||||
a new location for each @scheme[id], and places the values into the
|
||||
locations. It then evaluates the @scheme[body], in which the
|
||||
@scheme[id]s are bound. (See @secref["intdef-body"] for information
|
||||
on @scheme[body] forms.) The last expression in @scheme[body] is in
|
||||
tail position with respect to the @scheme[let] form. The @scheme[id]s
|
||||
must be distinct according to @scheme[bound-identifier=?].
|
||||
|
||||
@examples[
|
||||
(let ([x 5]) x)
|
||||
(let ([x 5])
|
||||
(let ([x 2]
|
||||
[y x])
|
||||
(list y x)))
|
||||
]
|
||||
|
||||
The second form evaluates the @scheme[init-expr]s; the resulting
|
||||
values become arguments in an application of a procedure
|
||||
@scheme[(lambda (id ...) . body)], where @scheme[proc-id] is bound
|
||||
within @scheme[body] to the procedure itself.}
|
||||
|
||||
@examples[
|
||||
(let fac ([n 10])
|
||||
(if (zero? n)
|
||||
1
|
||||
(* n (fac (sub1 n)))))
|
||||
]
|
||||
|
||||
@defform[(let* ([id val-expr] ...) . body)]{
|
||||
|
||||
Similar to @scheme[let], but evaluates the @scheme[val-expr]s one by
|
||||
one, creating a location for each @scheme[id] as soon as the value is
|
||||
available, and binding @scheme[id] in the remaining @scheme[val-expr]s
|
||||
as well as the @scheme[body]. The @scheme[id]s need not be distinct.
|
||||
|
||||
@examples[
|
||||
(let ([x 1]
|
||||
[y (+ x 1)])
|
||||
(list y x))
|
||||
]}
|
||||
|
||||
@defform[(letrec ([id val-expr] ...) . body)]{
|
||||
|
||||
Similar to @scheme[let], but the locations for all @scheme[id]s are
|
||||
created first and filled with @|undefined-const|, and all
|
||||
@scheme[id]s are bound in all @scheme[val-expr]s as well as
|
||||
@scheme[body]. The @scheme[id]s must be distinct according to
|
||||
@scheme[bound-identifier=?].
|
||||
|
||||
@examples[
|
||||
(letrec ([is-even? (lambda (n)
|
||||
(or (zero? n)
|
||||
(is-odd? (sub1 n))))]
|
||||
[is-odd? (lambda (n)
|
||||
(or (= n 1)
|
||||
(is-even? (sub1 n))))])
|
||||
(is-odd? 11))
|
||||
]}
|
||||
|
||||
@defform[(let-values ([(id ...) val-expr] ...) . body)]{ Like
|
||||
@scheme[let], except that each @scheme[val-expr] must produce as many
|
||||
values as corresponding @scheme[id]s. A separate location is created
|
||||
for each @scheme[id], all of which are bound in the @scheme[body].
|
||||
|
||||
@examples[
|
||||
(let-values ([(x y) (quotient/remainder 10 3)])
|
||||
(list y x))
|
||||
]}
|
||||
|
||||
@defform[(let*-values ([(id ...) val-expr] ...) . body)]{ Like
|
||||
@scheme[let*], except that each @scheme[val-expr] must produce as many
|
||||
values as corresponding @scheme[id]s. A separate location is created
|
||||
for each @scheme[id], all of which are bound in the later
|
||||
@scheme[val-expr]s and in the @scheme[body].
|
||||
|
||||
@examples[
|
||||
(let*-values ([(x y) (quotient/remainder 10 3)]
|
||||
[(z) (list y x)])
|
||||
z)
|
||||
]}
|
||||
|
||||
@defform[(letrec-values ([(id ...) val-expr] ...) . body)]{ Like
|
||||
@scheme[letrec], except that each @scheme[val-expr] must produce as
|
||||
many values as corresponding @scheme[id]s. A separate location is
|
||||
created for each @scheme[id], all of which are initialized to
|
||||
@|undefined-const| and bound in all @scheme[val-expr]s
|
||||
and in the @scheme[body].
|
||||
|
||||
@examples[
|
||||
(letrec-values ([(is-even? is-odd?)
|
||||
(values
|
||||
(lambda (n)
|
||||
(or (zero? n)
|
||||
(is-odd? (sub1 n))))
|
||||
(lambda (n)
|
||||
(or (= n 1)
|
||||
(is-even? (sub1 n)))))])
|
||||
(is-odd? 11))
|
||||
]}
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Sequencing: @scheme[begin]}
|
||||
|
||||
|
|
|
@ -307,9 +307,9 @@ for the index entry.}
|
|||
@defthing[PLaneT string?]{@scheme["PLaneT"] (to help make sure you get
|
||||
the letters in the right case).}
|
||||
|
||||
@defproc[(void-const) any/c]{Returns @scheme["void"], as opposed to
|
||||
@scheme[(scheme void)]---but we may eventually find a clearer way to
|
||||
refer to @void-const in prose.}
|
||||
@defthing[void-const element?]{Returns an element for @|void-const|.}
|
||||
|
||||
@defthing[undefined-const element?]{Returns an element for @|undefined-const|.}
|
||||
|
||||
@defproc[(centerline [pre-flow any/c] ...0) table?]{Produces a
|
||||
centered table with the @scheme[pre-flow] parsed by
|
||||
|
|
Loading…
Reference in New Issue
Block a user