guide and reference work; change opt-lambda to use lambda/kw and hack in keyword support for documentation purposes, along with define-opt
svn: r6572
This commit is contained in:
parent
0d69b92c79
commit
32e9101594
|
@ -1,7 +1,8 @@
|
|||
|
||||
(module etc mzscheme
|
||||
|
||||
(require (lib "main-collects.ss" "setup"))
|
||||
(require (lib "main-collects.ss" "setup")
|
||||
"kw.ss")
|
||||
|
||||
(require-for-syntax (lib "kerncase.ss" "syntax")
|
||||
(lib "stx.ss" "syntax")
|
||||
|
@ -23,6 +24,7 @@
|
|||
loop-until
|
||||
|
||||
opt-lambda
|
||||
define-opt
|
||||
|
||||
local
|
||||
recur
|
||||
|
@ -129,52 +131,82 @@
|
|||
(eq? x y))
|
||||
|
||||
(define-syntax (opt-lambda stx)
|
||||
(with-syntax ([name (or (syntax-local-infer-name stx)
|
||||
(quote-syntax opt-lambda-proc))])
|
||||
(syntax-case stx ()
|
||||
[(_ args body1 body ...)
|
||||
(let ([clauses (let loop ([pre-args null]
|
||||
[args (syntax args)]
|
||||
[needs-default? #f])
|
||||
(syntax-case args ()
|
||||
[id
|
||||
(identifier? (syntax id))
|
||||
(with-syntax ([(pre-arg ...) pre-args])
|
||||
(syntax ([(pre-arg ... . id)
|
||||
body1 body ...])))]
|
||||
[()
|
||||
(with-syntax ([(pre-arg ...) pre-args])
|
||||
(syntax ([(pre-arg ...)
|
||||
body1 body ...])))]
|
||||
[(id . rest)
|
||||
(identifier? (syntax id))
|
||||
(begin
|
||||
(when needs-default?
|
||||
(raise-syntax-error
|
||||
#f "default value missing" stx (syntax id)))
|
||||
(loop (append pre-args (list (syntax id)))
|
||||
(syntax rest)
|
||||
#f))]
|
||||
[([id default] . rest)
|
||||
(identifier? (syntax id))
|
||||
(with-syntax ([rest (loop (append pre-args (list (syntax id)))
|
||||
(syntax rest)
|
||||
#t)]
|
||||
[(pre-arg ...) pre-args])
|
||||
(syntax ([(pre-arg ...) (name pre-arg ... default)]
|
||||
. rest)))]
|
||||
[(bad . rest)
|
||||
(raise-syntax-error
|
||||
#f
|
||||
"not an identifier or identifier with default"
|
||||
stx
|
||||
(syntax bad))]
|
||||
[else
|
||||
(raise-syntax-error
|
||||
#f "bad identifier sequence" stx (syntax args))]))])
|
||||
(with-syntax ([clauses clauses])
|
||||
(syntax/loc stx
|
||||
(letrec ([name (case-lambda . clauses)]) name))))])))
|
||||
(syntax-case stx ()
|
||||
[(_ args body1 body ...)
|
||||
(with-syntax ([((plain ...) (opt ...) (kw ...) need-kw rest)
|
||||
(let loop ([args (syntax args)]
|
||||
[needs-default? #f])
|
||||
(syntax-case args ()
|
||||
[id
|
||||
(identifier? (syntax id))
|
||||
#'(() () () () (#:body id))]
|
||||
[()
|
||||
#'(() () () () ())]
|
||||
[(id . rest)
|
||||
(identifier? (syntax id))
|
||||
(begin
|
||||
(when needs-default?
|
||||
(raise-syntax-error
|
||||
#f "default value missing" stx (syntax id)))
|
||||
(with-syntax ([(plain opts kws need-kw rest) (loop #'rest #f)])
|
||||
#'((id . plain) opts kws need-kw rest)))]
|
||||
[([id default] . rest)
|
||||
(identifier? (syntax id))
|
||||
(with-syntax ([(plain opts kws need-kw rest) (loop #'rest #t)])
|
||||
#'(plain ([id default] . opts) kws need-kw rest))]
|
||||
[(kw id . rest)
|
||||
(and (identifier? #'id)
|
||||
(keyword? (syntax-e #'kw)))
|
||||
(with-syntax ([(plain opts kws need-kw rest) (loop #'rest needs-default?)])
|
||||
#'(plain opts ([id kw #f] . kws) (kw . need-kw) rest))]
|
||||
[(kw [id default] . rest)
|
||||
(and (identifier? #'id)
|
||||
(keyword? (syntax-e #'kw)))
|
||||
(with-syntax ([(plain opts kws need-kw rest) (loop #'rest needs-default?)])
|
||||
#'(plain opts ([id kw default] . kws) need-kw rest))]
|
||||
[(bad . rest)
|
||||
(raise-syntax-error
|
||||
#f
|
||||
"not an identifier or identifier with default"
|
||||
stx
|
||||
(syntax bad))]
|
||||
[else
|
||||
(raise-syntax-error
|
||||
#f "bad identifier sequence" stx (syntax args))]))])
|
||||
(let ([kw-proc (syntax/loc stx
|
||||
(lambda/kw [plain ... #:optional opt ... #:key kw ... . rest] body1 body ...))])
|
||||
(if (null? (syntax-e #'(kw ...)))
|
||||
kw-proc
|
||||
(with-syntax ([name (or (syntax-local-infer-name stx)
|
||||
(quote-syntax opt-lambda-proc))]
|
||||
[kw-proc kw-proc]
|
||||
[len (length (syntax->list #'(plain ...)))])
|
||||
(syntax/loc stx
|
||||
(let ([name kw-proc])
|
||||
(lambda all-args
|
||||
(apply name (sort-kws len 'need-kw all-args)))))))))]))
|
||||
|
||||
(define-syntax define-opt
|
||||
(syntax-rules ()
|
||||
[(_ (id . args) body1 body ...)
|
||||
(define id (opt-lambda args body1 body ...))]
|
||||
[(_ . rest) (define . rest)]))
|
||||
|
||||
(define (sort-kws len need-kw l)
|
||||
(for-each (lambda (kw)
|
||||
(unless (memq kw l)
|
||||
(error "missing required argument for" kw)))
|
||||
need-kw)
|
||||
(let loop ([len len][l l][kws null])
|
||||
(cond
|
||||
[(null? l) (append kws l)]
|
||||
[(zero? len) (append kws l)]
|
||||
[(and (keyword? (car l))
|
||||
(pair? (cdr l)))
|
||||
(loop len (cddr l) (list* (car l)
|
||||
(cadr l)
|
||||
kws))]
|
||||
[else (cons (car l) (loop (sub1 len) (cdr l) kws))])))
|
||||
|
||||
(define-syntax (local stx)
|
||||
(syntax-case stx ()
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
for/or for*/or
|
||||
for/first for*/first
|
||||
for/last for*/last
|
||||
|
||||
for/fold/derived for*/fold/derived
|
||||
|
||||
(rename *in-range in-range)
|
||||
(rename *in-naturals in-naturals)
|
||||
|
|
|
@ -210,9 +210,9 @@
|
|||
[(_ (eval:alts a b)) (schemeinput* a)]
|
||||
[(_ e) (schemeinput e)]))
|
||||
|
||||
(define (defspace p)
|
||||
(make-flow (list p
|
||||
(make-paragraph null))))
|
||||
(define-code schemeblock+line (to-paragraph/prefix (hspace 2)
|
||||
(hspace 2)
|
||||
(list " ")))
|
||||
|
||||
(define-syntax (schemedefinput* stx)
|
||||
(syntax-case stx (eval-example-string define define-struct)
|
||||
|
@ -220,13 +220,13 @@
|
|||
#'(schemeinput* (eval-example-string s))]
|
||||
[(_ (define . rest))
|
||||
(syntax-case stx ()
|
||||
[(_ e) #'(defspace (schemeblock e))])]
|
||||
[(_ e) #'(schemeblock+line e)])]
|
||||
[(_ (define-struct . rest))
|
||||
(syntax-case stx ()
|
||||
[(_ e) #'(defspace (schemeblock e))])]
|
||||
[(_ e) #'(schemeblock+line e)])]
|
||||
[(_ (code:line (define . rest) . rest2))
|
||||
(syntax-case stx ()
|
||||
[(_ e) #'(defspace (schemeblock e))])]
|
||||
[(_ e) #'(schemeblock+line e)])]
|
||||
[(_ e) #'(schemeinput e)]))
|
||||
|
||||
(define-syntax titled-interaction
|
||||
|
|
|
@ -75,7 +75,7 @@
|
|||
(pair? number))
|
||||
(printf "\\~a~a{"
|
||||
(case (length number)
|
||||
[(0 1) "section"]
|
||||
[(0 1) "newpage\n\n\\section"]
|
||||
[(2) "subsection"]
|
||||
[(3) "subsubsection"]
|
||||
[else "subsubsection*"])
|
||||
|
|
|
@ -150,7 +150,8 @@
|
|||
;; ----------------------------------------
|
||||
|
||||
(provide defproc defproc* defstruct defthing defform defform* defform/subs defform*/subs defform/none
|
||||
specform specsubform specsubform/inline
|
||||
specform specform/subs
|
||||
specsubform specspecsubform specsubform/inline
|
||||
schemegrammar
|
||||
var svar void-const undefined-const)
|
||||
|
||||
|
@ -250,15 +251,30 @@
|
|||
(define-syntax specsubform
|
||||
(syntax-rules ()
|
||||
[(_ spec desc ...)
|
||||
(*specsubform 'spec #f (lambda () (schemeblock0 spec)) (lambda () (list desc ...)))]))
|
||||
(*specsubform 'spec #f (lambda () (schemeblock0 spec)) null null (lambda () (list desc ...)))]))
|
||||
(define-syntax specspecsubform
|
||||
(syntax-rules ()
|
||||
[(_ spec desc ...)
|
||||
(make-blockquote "leftindent" (list (specsubform spec desc ...)))]))
|
||||
(define-syntax specform
|
||||
(syntax-rules ()
|
||||
[(_ spec desc ...)
|
||||
(*specsubform 'spec #t (lambda () (schemeblock0 spec)) (lambda () (list desc ...)))]))
|
||||
(*specsubform 'spec #t (lambda () (schemeblock0 spec)) null null (lambda () (list desc ...)))]))
|
||||
(define-syntax specform/subs
|
||||
(syntax-rules ()
|
||||
[(_ spec ([non-term-id non-term-form ...] ...) desc ...)
|
||||
(*specsubform 'spec #t
|
||||
(lambda () (schemeblock0 spec))
|
||||
'((non-term-id non-term-form ...) ...)
|
||||
(list (list (lambda () (scheme non-term-id))
|
||||
(lambda () (schemeblock0 non-term-form))
|
||||
...)
|
||||
...)
|
||||
(lambda () (list desc ...)))]))
|
||||
(define-syntax specsubform/inline
|
||||
(syntax-rules ()
|
||||
[(_ spec desc ...)
|
||||
(*specsubform 'spec #f #f (lambda () (list desc ...)))]))
|
||||
(*specsubform 'spec #f #f null null (lambda () (list desc ...)))]))
|
||||
(define-syntax defthing
|
||||
(syntax-rules ()
|
||||
[(_ id result desc ...)
|
||||
|
@ -523,9 +539,10 @@
|
|||
sub-procs))))
|
||||
(content-thunk)))))
|
||||
|
||||
(define (*specsubform form has-kw? form-thunk content-thunk)
|
||||
(define (*specsubform form has-kw? form-thunk subs sub-procs content-thunk)
|
||||
(parameterize ([current-variable-list
|
||||
(append (let loop ([form (if has-kw? (cdr form) form)])
|
||||
(append (let loop ([form (cons (if has-kw? (cdr form) form)
|
||||
subs)])
|
||||
(cond
|
||||
[(symbol? form) (if (meta-symbol? form)
|
||||
null
|
||||
|
@ -539,12 +556,20 @@
|
|||
(cons
|
||||
(make-table
|
||||
'boxed
|
||||
(list (list
|
||||
(make-flow
|
||||
(list
|
||||
(if form-thunk
|
||||
(form-thunk)
|
||||
(make-paragraph (list (to-element form)))))))))
|
||||
(cons
|
||||
(list
|
||||
(make-flow
|
||||
(list
|
||||
(if form-thunk
|
||||
(form-thunk)
|
||||
(make-paragraph (list (to-element form)))))))
|
||||
(apply
|
||||
append
|
||||
(map (lambda (sub)
|
||||
(list (list (make-flow (list (make-paragraph (list (tt 'nbsp))))))
|
||||
(list (make-flow (list (apply *schemerawgrammar
|
||||
(map (lambda (f) (f)) sub)))))))
|
||||
sub-procs))))
|
||||
(flow-paragraphs (decode-flow (content-thunk)))))))
|
||||
|
||||
(define (*schemerawgrammar nonterm clause1 . clauses)
|
||||
|
@ -643,5 +668,29 @@
|
|||
[else (list i)])))
|
||||
c)))))
|
||||
|
||||
;; ----------------------------------------
|
||||
|
||||
(provide cite)
|
||||
|
||||
(define/kw (cite #:key key title author location date)
|
||||
"[...]"
|
||||
#;
|
||||
(make-bibliography-element
|
||||
#f
|
||||
(list "[...]")
|
||||
key
|
||||
(list (string-append
|
||||
(content->string (list author))
|
||||
", "
|
||||
(content->string (list title))))
|
||||
(list (make-element #f (list author
|
||||
", "
|
||||
title
|
||||
", "
|
||||
date
|
||||
". "
|
||||
location
|
||||
".")))))
|
||||
|
||||
;; ----------------------------------------
|
||||
)
|
||||
|
|
|
@ -369,7 +369,6 @@
|
|||
(string? (syntax-e c))
|
||||
(bytes? (syntax-e c))
|
||||
(char? (syntax-e c))
|
||||
(keyword? (syntax-e c))
|
||||
(boolean? (syntax-e c)))
|
||||
value-color]
|
||||
[(identifier? c)
|
||||
|
@ -389,7 +388,12 @@
|
|||
(set! dest-col 0)
|
||||
(hash-table-put! next-col-map init-col dest-col)
|
||||
((loop (lambda () (set! src-col init-col) (set! dest-col 0)) 0) c)
|
||||
(out suffix #f)
|
||||
(if (list? suffix)
|
||||
(map (lambda (sfx)
|
||||
(finish-line!)
|
||||
(out sfx #f))
|
||||
suffix)
|
||||
(out suffix #f))
|
||||
(unless (null? content)
|
||||
(finish-line!))
|
||||
(if multi-line?
|
||||
|
|
|
@ -12,19 +12,19 @@ An expression of the form
|
|||
]
|
||||
|
||||
is a procedure application when @scheme[_proc-expr] is not an
|
||||
identifier that is bound as a transformer. The @scheme[...] in this
|
||||
syntactic sketch means ``zero or more repetitions of the preceding
|
||||
element.'' Specifically, it means zero or more @scheme[_arg-expr]s.
|
||||
identifier that is bound as a transformer.
|
||||
|
||||
@section{Evaluation Order and Arity}
|
||||
|
||||
A procedure application is evaluated by first evaluating the
|
||||
@scheme[_proc-expr] and all @scheme[_arg-expr]s in order (left to
|
||||
right). Then, if @scheme[_proc-expr] produced a procedure that accepts
|
||||
as many arguments as supplied @scheme[_arg-expr]s, the procedure is
|
||||
aplied. Otherwise, an exception is raised.
|
||||
applied. Otherwise, an exception is raised.
|
||||
|
||||
@examples[
|
||||
(cons 1 null)
|
||||
((lambda (x y z) (+ x y z)) 1 2 3)
|
||||
(+ 1 2 3)
|
||||
(cons 1 2 3)
|
||||
(1 2 3)
|
||||
]
|
||||
|
@ -32,19 +32,80 @@ aplied. Otherwise, an exception is raised.
|
|||
Some procedures, such as @scheme[cons], accept a fixed number of
|
||||
arguments. Some procedures, such as @scheme[list], accept any number
|
||||
of arguments. Some procedures accept a range of argument counts; for
|
||||
example @scheme[substring] accepts either two or three arguments.
|
||||
example @scheme[substring] accepts either two or three arguments. A
|
||||
procedure's @idefterm{arity} is the number(s) of arguments that it
|
||||
accepts.
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Keyword Arguments}
|
||||
|
||||
Some procedures accept @defterm{keyword arguments} in addition to
|
||||
by-position arguments. To supply a keyword argument, include a keyword
|
||||
followed by the addociated argument value. The order of keyword
|
||||
arguments does not matter, nor does their position relative to
|
||||
non-keyword arguments (as long as they follow the procedure
|
||||
expression); keyword arguments are recognized by an applied procedure
|
||||
using only the associated keyword, not the order.
|
||||
by-position arguments. For that case, an @scheme[_arg] can be an
|
||||
@scheme[_arg-keyword _arg-expr] sequence instead of just a
|
||||
@scheme[_arg-expr]:
|
||||
|
||||
@examples[
|
||||
(need-an-example 1 #:arg 2)
|
||||
(need-an-example #:arg 2 1)
|
||||
@specform/subs[
|
||||
(_proc-expr _arg ...)
|
||||
([arg arg-expr
|
||||
(code:line arg-keyword arg-expr)])
|
||||
]
|
||||
|
||||
For example,
|
||||
|
||||
@schemeblock[(go "super.ss" #:mode 'fast)]
|
||||
|
||||
calls the procedure bound to @scheme[go] with @scheme["super.ss"] as a
|
||||
by-position argument, and with @scheme['fast] as an argument associated
|
||||
with the @scheme[#:mode] keyword. Thus, a keyword is implicitly paired
|
||||
with the expression that follows it. Since a keyword by itself is not
|
||||
an expression, then
|
||||
|
||||
@schemeblock[(go "super.ss" #:mode #:fast)]
|
||||
|
||||
is a syntax error---because @scheme[#:fast] is not an expression.
|
||||
|
||||
The order of keyword @scheme[_arg]s determines the order in which
|
||||
@scheme[_arg-expr]s are evaluated, but a procedure accepts (or
|
||||
declines) keyword arguments independent of their position in the
|
||||
argument list. That is, keyword arguments are recognized by an applied
|
||||
procedure using only the associated keyword. The above call to
|
||||
@scheme[go] can be equivalently written
|
||||
|
||||
@schemeblock[(go #:mode #:fast "super.ss")]
|
||||
|
||||
@refdetails["mz:application"]{procedure applications}
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section[#:tag "guide:apply"]{The @scheme[apply] Procedure}
|
||||
|
||||
The syntax for procedure applications supports any number of
|
||||
arguments, but a specific application expression always specifies a
|
||||
fixed number of arguments. As a result, a procedure that takes a list
|
||||
of arguments cannot directly apply a procedure like @scheme[+] to all
|
||||
of the items in the list:
|
||||
|
||||
@def+int[
|
||||
(define (avg lst) (code:comment #, @elem{doesn't work...})
|
||||
(/ (+ lst) (length lst)))
|
||||
(avg '(1 2 3))
|
||||
]
|
||||
|
||||
@def+int[
|
||||
(define (avg lst) (code:comment #, @elem{doesn't always work...})
|
||||
(/ (+ (list-ref lst 0) (list-ref lst 1) (list-ref lst 2))
|
||||
(length lst)))
|
||||
(avg '(1 2 3))
|
||||
(avg '(1 2))
|
||||
]
|
||||
|
||||
The @scheme[apply] procedure offers a way around this restriction, It
|
||||
takes another procedure a @italic{list} arguments, and it applies the
|
||||
procedure to the arguments:
|
||||
|
||||
@def+int[
|
||||
(define (avg lst)
|
||||
(/ (apply + lst) (length lst)))
|
||||
(avg '(1 2 3))
|
||||
(avg '(1 2))
|
||||
(avg '(1 2 3 4))
|
||||
]
|
||||
|
|
|
@ -23,7 +23,7 @@ prints like the ASCII decoding of the byte string, but prefixed with a
|
|||
@litchar{#}. Unprintable ASCII characters or non-ASCII bytes in the
|
||||
byte string are written with octal notation.
|
||||
|
||||
@refdetails["mz:parse-string"]{the syntax of byte strings}
|
||||
@refdetails/gory["mz:parse-string"]{the syntax of byte strings}
|
||||
|
||||
@examples[
|
||||
#"Apple"
|
||||
|
@ -37,7 +37,7 @@ b
|
|||
]
|
||||
|
||||
The @scheme[display] form of a byte string writes its raw bytes to the
|
||||
current output port (see @secref["output"]). Technically,
|
||||
current output port (see @secref["guide:i/o"]). Technically,
|
||||
@scheme[display] of a normal (i.e,. character) string prints the UTF-8
|
||||
encoding of the string to the current output port, since output is
|
||||
ultimately defined in terms of bytes; @scheme[display] of a byte
|
||||
|
|
|
@ -15,10 +15,10 @@ to three octal digits, and hexadimal escapes with @litchar["\\u"]
|
|||
(up to four digits). Unprintable characters in a string normally
|
||||
shown with @litchar["\\u"] when the string is printed.
|
||||
|
||||
@refdetails["mz:parse-string"]{the syntax of strings}
|
||||
@refdetails/gory["mz:parse-string"]{the syntax of strings}
|
||||
|
||||
The @scheme[display] procedure directly writes the characters of a
|
||||
string to the current output port (see @secref["output"]), in contrast
|
||||
string to the current output port (see @secref["guide:i/o"]), in contrast
|
||||
to the string-constant syntax used to print a string result.
|
||||
|
||||
@examples[
|
||||
|
|
|
@ -26,7 +26,7 @@ number. A few characters are printed specially; for example, the space
|
|||
and linefeed characters print as @scheme[#\space] and
|
||||
@scheme[#\newline], respectively.
|
||||
|
||||
@refdetails["mz:parse-character"]{the syntax of characters}
|
||||
@refdetails/gory["mz:parse-character"]{the syntax of characters}
|
||||
|
||||
@examples[
|
||||
(integer->char 65)
|
||||
|
@ -38,7 +38,7 @@ and linefeed characters print as @scheme[#\space] and
|
|||
]
|
||||
|
||||
The @scheme[display] procedure directly writes a character to the
|
||||
current output port (see @secref["output"]), in contrast to the
|
||||
current output port (see @secref["guide:i/o"]), in contrast to the
|
||||
character-constant syntax used to print a character result.
|
||||
|
||||
@examples[
|
||||
|
|
|
@ -17,9 +17,9 @@ objects to @secref["classes"].
|
|||
|
||||
To a first approximation, the syntax of @scheme[define-struct] is
|
||||
|
||||
@schemeblock[
|
||||
(define-struct _struct-id (_field-id ...))
|
||||
]
|
||||
@specform[
|
||||
(define-struct struct-id (field-id ...))
|
||||
]{}
|
||||
|
||||
Such a definition binds @scheme[_struct-id], but only to static
|
||||
information about the structure type that cannot be used directly:
|
||||
|
@ -71,13 +71,13 @@ are built from @scheme[_struct-id] and the @scheme[_field-id]s:
|
|||
}
|
||||
|
||||
A @scheme[define-struct] form places no constraints on the kinds of
|
||||
values that can appears for fields in an instance of the structure
|
||||
values that can appear for fields in an instance of the structure
|
||||
type. For example, @scheme[(make-posn "apple" #f)] produces an
|
||||
instance of @scheme[posn], even though @scheme["apple"] and
|
||||
@scheme[#f] are not valid co-ordinates for the obvious uses of
|
||||
@scheme[#f] are not valid coordinates for the obvious uses of
|
||||
@scheme[posn] instances. Enforcing constraints on field values, such
|
||||
as requiring them to be numbers, is the job of a contract, as
|
||||
discussed later in @secref["contracts"].
|
||||
discussed later in @secref["guide:contracts"].
|
||||
|
||||
@; ------------------------------------------------------------
|
||||
@section{Structure Subtypes}
|
||||
|
@ -86,8 +86,8 @@ An extended form of @scheme[defin-struct] can be used to define a
|
|||
@defterm{structure subtype}, which is a structure type that extends an
|
||||
existing structure type:
|
||||
|
||||
@schemeblock[
|
||||
(define-struct (_struct-id _super-id) (_field-id ...))
|
||||
@specform[
|
||||
(define-struct (struct-id super-id) (field-id ...))
|
||||
]
|
||||
|
||||
The @scheme[_super-id] must be a structure type name bound by
|
||||
|
@ -133,13 +133,19 @@ To make a structure type @defterm{transparent}, use the
|
|||
field-name sequence:
|
||||
|
||||
@def+int[
|
||||
(define-struct posn (x y)
|
||||
#f)
|
||||
'(define-struct posn (x y)
|
||||
#:inspector #f)
|
||||
(make-posn 1 2)
|
||||
]
|
||||
|
||||
An instance of a transparent structure type prints like a vector, and
|
||||
it shows the content of the structure's fields. A transparent
|
||||
structure type allows allows reflective operations like
|
||||
@scheme[struct?] and @scheme[struct-info] to be used on its
|
||||
structure type also allows reflective operations, like
|
||||
@scheme[struct?] and @scheme[struct-info], to be used on its
|
||||
instances (see @secref["reflection"]).
|
||||
|
||||
Structure types are opaque by default, because opaque structure
|
||||
instances provide more encapsulation guarantees. That is, a library
|
||||
can use an opaque structure to encapsulate data, and clients of the
|
||||
library cannot manipulate the data in the structure except as allowed
|
||||
by the library.
|
||||
|
|
|
@ -3,8 +3,117 @@
|
|||
@require[(lib "eval.ss" "scribble")]
|
||||
@require["guide-utils.ss"]
|
||||
|
||||
@interaction-eval[(require (rename (lib "etc.ss") define define-opt))]
|
||||
|
||||
@title{Definitions: @scheme[define] and @scheme[define-values]}
|
||||
|
||||
A definition can have the form
|
||||
A basic definition has the form
|
||||
|
||||
@specform[(define _id _expr)]
|
||||
@specform[(define id expr)]{}
|
||||
|
||||
in which case @scheme[_id] is bound to the result of
|
||||
@scheme[_expr].
|
||||
|
||||
@defexamples[
|
||||
(define salutation (list-ref '("Hi" "Hello") (random 2)))
|
||||
salutation
|
||||
]
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Procedure Shorthand}
|
||||
|
||||
The @scheme[define] form also supports a shorthand for procedure
|
||||
definitions:
|
||||
|
||||
@specform[(define (id arg ...) body ...+)]{}
|
||||
|
||||
which is a shorthand for
|
||||
|
||||
@schemeblock[
|
||||
(define id (lambda (arg ...) _body ...+))
|
||||
]
|
||||
|
||||
@defexamples[
|
||||
(define (greet name)
|
||||
(string-append salutation ", " name))
|
||||
(greet "John")
|
||||
]
|
||||
|
||||
@def+int[
|
||||
(define (greet first [surname "Smith"] #:hi [hi salutation])
|
||||
(string-append hi ", " first " " surname))
|
||||
(greet "John")
|
||||
(greet "John" #:hi "Hey")
|
||||
(greet "John" "Doe")
|
||||
]
|
||||
|
||||
The procedure shorthand via @scheme[define] also supports a final
|
||||
argument to collect extra arguments in a list:
|
||||
|
||||
@specform[(define (id arg ... . rest-id) expr)]{}
|
||||
|
||||
which is a shorthand
|
||||
|
||||
@schemeblock[
|
||||
(define id (lambda (id arg ... . rest-id) body-expr ...+))
|
||||
]
|
||||
|
||||
@defexamples[
|
||||
(define (avg . l)
|
||||
(/ (apply + l) (length l)))
|
||||
(avg 1 2 3)
|
||||
]
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section[#:tag "guide:multiple-values"]{Multiple Values}
|
||||
|
||||
A Scheme expression normally produces a single result, but some
|
||||
expressions can produce multiple results. For example,
|
||||
@scheme[quotient] and @scheme[remainder] each produce a single value,
|
||||
but @scheme[quotient/remainder] produces the same two values at once:
|
||||
|
||||
@interaction[
|
||||
(quotient 13 3)
|
||||
(remainder 13 3)
|
||||
(quotient/remainder 13 3)
|
||||
]
|
||||
|
||||
As shown abpve, the REPL prints each result value on its own line.
|
||||
|
||||
Multiple-valued procedures can be implemented in terms of the
|
||||
@scheme[values] procedure, which takes any number of values and
|
||||
returns them as the results:
|
||||
|
||||
@interaction[
|
||||
(values 1 2 3)
|
||||
]
|
||||
@def+int[
|
||||
(define (split-name name)
|
||||
(let ([m (regexp-match #rx"^([^ ]*) (.*)$" name)])
|
||||
(values (list-ref m 1) (list-ref m 2))))
|
||||
(split-name "Adam Smith")
|
||||
]
|
||||
|
||||
The @scheme[define-values] form binds multiple identifiers at once to
|
||||
multiple results produced from a single expression:
|
||||
|
||||
@specform[(define-values (id ...) expr)]{}
|
||||
|
||||
The number of results produced by the @scheme[_expr] must match the
|
||||
number of @scheme[_id]s.
|
||||
|
||||
@defexamples[
|
||||
(define-values (given surname) (split-name "Adam Smith"))
|
||||
given
|
||||
surname
|
||||
]
|
||||
|
||||
A @scheme[define] form (that is not a procedure shorthand) is
|
||||
equivalent to a @scheme[define-values] form with a single @scheme[id].
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section[#:tag "guide:intdefs"]{Internal Definitions}
|
||||
|
||||
When the grammar for a syntactic form specified @scheme[_body], then
|
||||
the corresponding position in an instance of the grammar can be either
|
||||
a definition or an expression.
|
||||
|
|
|
@ -6,12 +6,78 @@
|
|||
@title[#:tag "scheme-forms" #:style 'toc]{Expressions and Definitions}
|
||||
|
||||
The @secref["to-scheme"] chapter introduced some of Scheme's syntactic
|
||||
forms: definitions, procedure applications, conditionals, procedures,
|
||||
local binding, and some iteration forms. This section provides a more
|
||||
complete coverage of the basic Scheme syntactic forms.
|
||||
forms: definitions, procedure applications, conditionals, and so
|
||||
on. This section provides more details on those forms, plus a few
|
||||
additional basic forms.
|
||||
|
||||
@local-table-of-contents[]
|
||||
|
||||
@section[#:tag "guide:syntax-notation"]{Notation}
|
||||
|
||||
This chapter (and the rest of the documentation) uses a slightly
|
||||
different notation than the character-based grammars of the
|
||||
@secref["to-scheme"] chapter. The grammar for a use of a syntactic
|
||||
form @schemekeywordfont{something} is shown like this:
|
||||
|
||||
@specform[(#,(schemekeywordfont "something") [id ...+] an-expr ...)]
|
||||
|
||||
The italicized meta-variables in this specification, such as
|
||||
@scheme[_id] and @scheme[_an-expr], use the syntax of Scheme
|
||||
identifiers, so @scheme[_an-expr] is one meta-variable. A naming
|
||||
convention implicitly defines the meaning of many meta-variables:
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{A meta-variable that ends in @scheme[_id] stands for an
|
||||
identifier, such as @schemeidfont{x} or
|
||||
@schemeidfont{my-favorite-martian}.}
|
||||
|
||||
@item{A meta-identifier that ends in @scheme[_keyword] stands
|
||||
for a keyword, such as @scheme[#:tag].}
|
||||
|
||||
@item{A meta-identifier that ends with @scheme[_expr] stands for any
|
||||
sub-form, and it will be parsed as an expression.}
|
||||
|
||||
@item{A meta-identifier that ends with @scheme[_body] stands for any
|
||||
sub-form; it will be parsed as either a local definition or an
|
||||
expression. A @scheme[_body] can parse as a definition only if
|
||||
it is not preceded by any expression, and the last
|
||||
@scheme[_body] must be an expression.}
|
||||
|
||||
}
|
||||
|
||||
Square brackets in the grammar indicate a parenthesized sequence of
|
||||
forms, where square brackets are normally used (by convention). That
|
||||
is square brackets @italic{do not} mean optional parts of the
|
||||
syntactic form.
|
||||
|
||||
A @scheme[...] indicates zero or more repetitions of the preceding
|
||||
form, and @scheme[...+] indicates one or more repetitions of the
|
||||
preceding datum. Otherwise, non-italicized identifiers stand form
|
||||
themselves.
|
||||
|
||||
Based on the above grammar, then, here are a few legal uses of
|
||||
@schemekeywordfont{something}:
|
||||
|
||||
@schemeblock[
|
||||
(#,(schemekeywordfont "something") [x])
|
||||
(#,(schemekeywordfont "something") [x] (+ 1 2))
|
||||
(#,(schemekeywordfont "something") [x my-favorite-martian x] (+ 1 2) #f)
|
||||
]
|
||||
|
||||
Some syntactic forms refer to meta-variables that are not implicitly
|
||||
defined and not previously defined. Such meta-variables are defined
|
||||
using a BNF-like format for alternatives:
|
||||
|
||||
@specform/subs[(#,(schemekeywordfont "something-else") [thing ...+] an-expr ...)
|
||||
([thing thing-id
|
||||
thing-keyword])]
|
||||
|
||||
The above example says that, within a @schemekeywordfont{something-else}
|
||||
form, a @scheme[_thing] is either an identifier or a keyword.
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
|
||||
@include-section["binding.scrbl"]
|
||||
@include-section["apply.scrbl"]
|
||||
@include-section["lambda.scrbl"]
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
(provide Quick MzScheme HtDP
|
||||
tool
|
||||
refdetails
|
||||
refdetails/gory
|
||||
refsecref)
|
||||
|
||||
(define Quick
|
||||
|
@ -21,13 +22,19 @@
|
|||
(define (tool name . desc)
|
||||
(apply item (bold name) ", " desc))
|
||||
|
||||
(define/kw (refdetails tag #:body s)
|
||||
(define/kw (refdetails* tag what #:body s)
|
||||
(apply margin-note
|
||||
(decode-content (append (list "For more on ")
|
||||
(decode-content (append (list "For " what " on ")
|
||||
s
|
||||
(list ", see "
|
||||
(refsecref tag)
|
||||
".")))))
|
||||
|
||||
(define/kw (refdetails tag #:body s)
|
||||
(apply refdetails* tag "more" s))
|
||||
|
||||
(define/kw (refdetails/gory tag #:body s)
|
||||
(apply refdetails* tag "gory details" s))
|
||||
|
||||
(define (refsecref s)
|
||||
(make-element #f (list (secref s) " in " MzScheme))))
|
||||
|
|
|
@ -24,14 +24,14 @@ precise details to @|MzScheme| and other reference manuals.
|
|||
|
||||
@include-section["data.scrbl"]
|
||||
|
||||
@include-section["define-struct.scrbl"]
|
||||
|
||||
@include-section["forms.scrbl"]
|
||||
|
||||
@include-section["define-struct.scrbl"]
|
||||
|
||||
@include-section["module-basics.scrbl"]
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "contracts"]{Contracts}
|
||||
@section[#:tag "guide:contracts"]{Contracts}
|
||||
|
||||
In the reference manual, the documentation for each procedure
|
||||
describes the acceptable arguments and the result of the procedure
|
||||
|
@ -54,7 +54,11 @@ using @idefterm{contracts}.
|
|||
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "i/o"]{I/O and Networking}
|
||||
@section[#:tag "guide:i/o"]{Input and Output}
|
||||
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "guide:networking"]{Networking}
|
||||
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
@ -88,6 +92,9 @@ using @idefterm{contracts}.
|
|||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "memory-management"]{Memory Management}
|
||||
|
||||
@subsection[#:tag "guide:weakboxes"]{Weak Boxes}
|
||||
|
||||
@subsection[#:tag "guide:ephemerons"]{Ephemerons}
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "performance"]{Performance}
|
||||
|
|
|
@ -33,7 +33,7 @@ key--value pair. Literal hash tables are immutable.
|
|||
(hash-table-get ht "apple")
|
||||
]
|
||||
|
||||
@refdetails["mz:parse-hashtable"]{the syntax of hash table literals}
|
||||
@refdetails/gory["mz:parse-hashtable"]{the syntax of hash table literals}
|
||||
|
||||
A hash table can optionally retain its keys @defterm{weakly}, so each
|
||||
mapping is retained only so long as the key is retained elsewhere.
|
||||
|
@ -49,7 +49,7 @@ Beware that even a weak hash table retains its values strongly, as
|
|||
long as the corresponding key is accessible. This creates a catch-22
|
||||
dependency when a value refers back to its key, so that the mapping is
|
||||
retained permanently. To break the cycle, map the key to an
|
||||
@seclink["ephemerons"]{ephemeron} that pair the value with its key (in
|
||||
@seclink["guide:ephemerons"]{ephemeron} that pair the value with its key (in
|
||||
addition to the implicit pairing of the hash table).
|
||||
|
||||
@examples[
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
|
||||
@title[#:tag "keywords"]{Keywords}
|
||||
|
||||
A @defterm{keyword} is similar to a symbol (see @secref["symbols"]),
|
||||
A @defterm{keyword} is similar to a symbol (see @secref["guide:symbols"]),
|
||||
but its printed form is prefixed with @litchar{#:}.
|
||||
|
||||
@refdetails["mz:parse-keyword"]{the syntax of keywords}
|
||||
@refdetails/gory["mz:parse-keyword"]{the syntax of keywords}
|
||||
|
||||
@examples[
|
||||
(string->keyword "apple")
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
@require[(lib "eval.ss" "scribble")]
|
||||
@require["guide-utils.ss"]
|
||||
|
||||
@interaction-eval[(require (rename (lib "etc.ss") lambda opt-lambda))]
|
||||
|
||||
@title[#:tag "guide:lambda"]{Procedures: @scheme[lambda] and @scheme[case-lambda]}
|
||||
|
||||
A @scheme[lambda] expression creates a procedure. In the simplest
|
||||
|
@ -10,13 +12,9 @@ case, a @scheme[lambda] expression has the form
|
|||
|
||||
@specform[
|
||||
(lambda (arg-id ...)
|
||||
body-expr ...+)
|
||||
body ...+)
|
||||
]
|
||||
|
||||
The @scheme[...+] in this syntactic sketch means ``one or more
|
||||
repetitions of the preceeding element.'' Specifically, it means one or
|
||||
more @scheme[_body-expr]s.
|
||||
|
||||
A @scheme[lambda] form with @math{n} @scheme[_arg-id]s accepts
|
||||
@math{n} arguments:
|
||||
|
||||
|
@ -29,11 +27,14 @@ A @scheme[lambda] form with @math{n} @scheme[_arg-id]s accepts
|
|||
1)
|
||||
]
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Rest Arguments}
|
||||
|
||||
A @scheme[lambda] expression can also have the form
|
||||
|
||||
@specform[
|
||||
(lambda rest-id
|
||||
body-expr ...+)
|
||||
body ...+)
|
||||
]
|
||||
|
||||
That is, a @scheme[lambda] expression can have a single
|
||||
|
@ -49,108 +50,160 @@ into a list bound to @scheme[_rest-id].
|
|||
1 2 3)
|
||||
]
|
||||
|
||||
Combining thes two styles, a @scheme[lambda] expression can have the
|
||||
form
|
||||
Procedures of this form often use @scheme[apply] to call another
|
||||
procedure that accepts any number of arguments.
|
||||
|
||||
@margin-note{See @secref["guide:apply"] for more information on
|
||||
@scheme[apply].}
|
||||
|
||||
@defexamples[
|
||||
(define max-mag
|
||||
(lambda nums
|
||||
(apply max (map magnitude nums))))
|
||||
|
||||
(max 1 -2 0)
|
||||
(max-mag 1 -2 0)
|
||||
]
|
||||
|
||||
Generalizing the fixed-arity and any-arity style, a @scheme[lambda]
|
||||
expression can have the form
|
||||
|
||||
@specform[
|
||||
(lambda (arg-id ...+ . rest-id)
|
||||
body-expr ...+)
|
||||
body ...+)
|
||||
]
|
||||
|
||||
The result is a procedure that requires at least as many arguments as
|
||||
@scheme[_arg-id]s, and also accepts any number of additional
|
||||
arguments.
|
||||
|
||||
@examples[
|
||||
((lambda (a b . x) (cons (/ a b) x))
|
||||
1 2 3 4)
|
||||
((lambda (a b . x) (cons (/ a b) x))
|
||||
1 2)
|
||||
((lambda (a b . x) (cons (/ a b) x))
|
||||
1)
|
||||
@defexamples[
|
||||
(define max-mag
|
||||
(lambda (num . nums)
|
||||
(apply max (map magnitude (cons num nums)))))
|
||||
|
||||
(max-mag 1 -2 0)
|
||||
(max-mag)
|
||||
]
|
||||
|
||||
Support for optional and keyword arguments lead to even more
|
||||
possibilities:
|
||||
A @scheme[_rest-id] variable is sometimes called a @defterm{rest
|
||||
argument}, because it accepts the ``rest'' of the procedure arguments.
|
||||
|
||||
@itemize{
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Optional Arguments}
|
||||
|
||||
@item{Instead of just an @scheme[_arg-id], an form argument can be
|
||||
@scheme[[_arg-id _default-expr]], which means that the argument
|
||||
is optional. When the argument is not supplied,
|
||||
@scheme[_default-expr] produces the default value. The
|
||||
@scheme[_default-expr] can refer to any preceding
|
||||
@scheme[_arg-id], and every following @scheme[_arg-id] must
|
||||
have a default as well.
|
||||
Instead of just an identifier, an argument (other than a rest
|
||||
argument) in a @scheme[lambda] form can be specified with an
|
||||
identifier and a default value:
|
||||
|
||||
@examples[
|
||||
((lambda (x [y 5]) (list x y))
|
||||
1 2)
|
||||
((lambda (x [y 5]) (list x y))
|
||||
1)
|
||||
((lambda (x [y (+ x 1)]) (list x y))
|
||||
1)
|
||||
(lambda ([x 5] y) (list x y))
|
||||
]}
|
||||
@specform/subs[
|
||||
(lambda (arg ...+ . rest-id)
|
||||
body ...+)
|
||||
([arg arg-id
|
||||
[arg-id default-expr]])
|
||||
]{}
|
||||
|
||||
@item{Instead of just an @scheme[_arg-id], an form argument can be
|
||||
@scheme[(code:line _keyword _arg-id)], which indicates a
|
||||
by-keyword argument instead of a by-position argument. The
|
||||
position of the keyword--identifier pair in the argument list
|
||||
does not matter for matching with arguments in an application,
|
||||
because it will be matched to an argument value by keyword
|
||||
insteda of by position.
|
||||
A argument of the form @scheme[[arg-id default-expr]] is
|
||||
optional. When the argument is not supplied in an application,
|
||||
@scheme[_default-expr] produces the default value. The
|
||||
@scheme[_default-expr] can refer to any preceding @scheme[_arg-id],
|
||||
and every following @scheme[_arg-id] must have a default as well.
|
||||
|
||||
@examples[
|
||||
((lambda (x #:second y) (list x y))
|
||||
1 #:second 2)
|
||||
((lambda (x #:second y) (list x y))
|
||||
#:second 2 1)
|
||||
((lambda (#:second y x) (list x y))
|
||||
1 #:second 2)
|
||||
((lambda (x #:second y) (list x y))
|
||||
1 2)
|
||||
((lambda (x #:second y) (list x y))
|
||||
#:second 2)
|
||||
]}
|
||||
@defexamples[
|
||||
(define greet
|
||||
(lambda (given [surname "Smith"])
|
||||
(string-append "Hello, " given " " surname)))
|
||||
|
||||
@item{The previous two possibilities can be combined to specify a
|
||||
by-keyword argument with a default value.
|
||||
(greet "John")
|
||||
(greet "John" "Doe")
|
||||
]
|
||||
|
||||
@examples[
|
||||
((lambda (x #:second [y 5]) (list x y))
|
||||
1 #:second 2)
|
||||
((lambda (x #:second [y 5]) (list x y))
|
||||
1)
|
||||
]}
|
||||
@def+int[
|
||||
(define greet
|
||||
(lambda (given [surname (if (equal? given "John")
|
||||
"Doe"
|
||||
"Smith")])
|
||||
(string-append "Hello, " given " " surname)))
|
||||
|
||||
}
|
||||
(greet "John")
|
||||
(greet "Adam")
|
||||
]
|
||||
|
||||
@section{Keyword Arguments}
|
||||
|
||||
A @scheme[lambda] form can declare an argument to be passed by
|
||||
keyword, instead of position. Keyword arguments can be mixed with
|
||||
by-position arguments, and default-value expressions can be supplied
|
||||
for either kind of argument:
|
||||
|
||||
@specform/subs[
|
||||
(lambda (arg ...+ . rest-id)
|
||||
body ...+)
|
||||
([arg arg-id
|
||||
[arg-id default-expr]
|
||||
(code:line arg-keyword arg-id)
|
||||
(code:line arg-keyword [arg-id default-expr])])
|
||||
]{}
|
||||
|
||||
As argument specified as @scheme[(code:line _arg-keyword _arg-id)] is
|
||||
supplied by an application using the same @scheme[_arg-keyword]. The
|
||||
position of the keyword--identifier pair in the argument list does not
|
||||
matter for matching with arguments in an application, because it will
|
||||
be matched to an argument value by keyword instead of by position.
|
||||
|
||||
@def+int[
|
||||
(define greet
|
||||
(lambda (given #:last surname)
|
||||
(string-append "Hello, " given " " surname)))
|
||||
|
||||
(greet "John" #:last "Smith")
|
||||
(greet #:last "Doe" "John")
|
||||
]
|
||||
|
||||
A @scheme[(code:line _arg-keyword [_arg-id _default-expr])] argument
|
||||
specifies a keyword-based argument with a default value.
|
||||
|
||||
@defexamples[
|
||||
(define greet
|
||||
(lambda (#:hi [hi "Hello"] given #:last [surname "Smith"])
|
||||
(string-append hi ", " given " " surname)))
|
||||
|
||||
(greet "John")
|
||||
(greet "Karl" #:last "Marx")
|
||||
(greet "John" #:hi "Howdy")
|
||||
(greet "Karl" #:last "Marx" #:hi "Guten Tag")
|
||||
]
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Arity-Sensitive Procedures: @scheme[case-lambda]}
|
||||
|
||||
The @scheme[case-lambda] form creates a procedure that can have
|
||||
completely different behaviors depending on the number of arguments
|
||||
that are supplied. A case-lambda expression has the form
|
||||
|
||||
@specform[
|
||||
@specform/subs[
|
||||
(case-lambda
|
||||
[formals body-expr ...+]
|
||||
[formals body ...+]
|
||||
...)
|
||||
([formals (arg-id ...)
|
||||
rest-id
|
||||
(arg-id ...+ . rest-id)])
|
||||
]
|
||||
|
||||
where each @scheme[_formals _body-expr ...+] is anlogous to
|
||||
@scheme[(lambda _formals _body-expr ...+)]. That is, a
|
||||
@scheme[_formals] can be @scheme[(_arg-id ...)], @scheme[_rest-id], or
|
||||
@scheme[(_arg-id ... . _rest-id)].
|
||||
where each @scheme[_formals _body ...+] is anlogous to @scheme[(lambda
|
||||
_formals _body ...+)]. Applying a procedure produced by
|
||||
@scheme[case-lambda] is like applying a @scheme[lambda] for the first
|
||||
case that matches the number of given arguments.
|
||||
|
||||
Applying a procedure produced by @scheme[case-lambda] is like applying
|
||||
a @scheme[lambda] for the first case that matches the number of given
|
||||
arguments.
|
||||
@defexamples[
|
||||
(define greet
|
||||
(case-lambda
|
||||
[(name) (string-append "Hello, " name)]
|
||||
[(given surname) (string-append "Hello, " given " " surname)]))
|
||||
|
||||
@examples[
|
||||
((case-lambda [() 10][(x y) (+ x y)])
|
||||
1 2)
|
||||
((case-lambda [() 10][(x y) (+ x y)]))
|
||||
((case-lambda [() 10][(x y) (+ x y)])
|
||||
1)
|
||||
(greet "John")
|
||||
(greet "John" "Smith")
|
||||
(greet)
|
||||
]
|
||||
|
||||
A @scheme[case-lambda] procedure cannot directly support optional or
|
||||
|
|
|
@ -179,7 +179,7 @@ With these pieces, you can write your own versions of the
|
|||
]
|
||||
|
||||
If the derivation of the above definitions is mysterious to you,
|
||||
consider reading @|HtDP|. But if you are merely suspicious of the use
|
||||
consider reading @|HtDP|. If you are merely suspicious of the use
|
||||
of recursive calls instead of a looping construct, then read on.
|
||||
|
||||
Both the @scheme[my-length] and @scheme[my-map] procedures run in
|
||||
|
|
|
@ -53,7 +53,7 @@ or inexact number. The prefixes @litchar{#b}, @litchar{#o}, and
|
|||
@litchar{#x} specificy binary, octal, and hexadecimal
|
||||
interprertation of digits.
|
||||
|
||||
@refdetails["mz:parse-number"]{the syntax of numbers}
|
||||
@refdetails/gory["mz:parse-number"]{the syntax of numbers}
|
||||
|
||||
@examples[
|
||||
0.5
|
||||
|
|
|
@ -43,7 +43,9 @@ with @file{~}---which looks like a reference to the current user's
|
|||
home directory, instead of a relative path to a file of directory
|
||||
named @file{~}. Windows path manipulation, furthermore, is far
|
||||
trickier, because path elements like @file{aux} can have special
|
||||
meanings (see @secref["windows-path"]).
|
||||
meanings.
|
||||
|
||||
@refdetails/gory["mz:windows-path"]{Windows filesystem paths}
|
||||
|
||||
Use procedures like @scheme[split-path] and @scheme[build-path] to
|
||||
deconstruct and construct paths. When you must manipulate the name of
|
||||
|
|
|
@ -47,7 +47,7 @@ a sequence as an element for repetition.
|
|||
@define[and-expr-stx @BNF-seq[@litchar{(} @litchar{and} @kleenestar{@nonterm{expr}} @litchar{)}]]
|
||||
@define[or-expr-stx @BNF-seq[@litchar{(} @litchar{or} @kleenestar{@nonterm{expr}} @litchar{)}]]
|
||||
@define[cond-expr-stx @BNF-seq[@litchar{(} @litchar{cond}
|
||||
@kleenestar{@BNF-group[@litchar{[} @nonterm{expr} @nonterm{expr} @litchar{]}]}
|
||||
@kleenestar{@BNF-group[@litchar{[} @nonterm{expr} @kleenestar{@nonterm{expr}} @litchar{]}]}
|
||||
@litchar{)}]]
|
||||
@define[(make-let-expr-stx kw)
|
||||
@BNF-seq[@litchar{(} kw @litchar{(}
|
||||
|
@ -328,13 +328,13 @@ The shorthand for a sequence of tests is the @scheme[cond] form:
|
|||
|
||||
A @scheme[cond] form contains a sequence of clauses between square
|
||||
brackets. In each clause, the first @nonterm{expr} is a test
|
||||
expression. If it produces true, then the clause's second
|
||||
@nonterm{expr} provides the answer for the entire @scheme[cond]
|
||||
expression, and the rest of the clauses are ignored. If the test
|
||||
@nonterm{expr} produces @scheme[#f], then the clause's second
|
||||
@nonterm{expr} is ignored, and evaluation continues with the
|
||||
next clause. The last clause can use @scheme[else] as a synonym for
|
||||
a @scheme[#t] test expression.
|
||||
expression. If it produces true, then the clause's remaining
|
||||
@nonterm{expr}s are evaluated, and the last one in the clause provides
|
||||
the answer for the entire @scheme[cond] expression; the rest of the
|
||||
clauses are ignored. If the test @nonterm{expr} produces @scheme[#f],
|
||||
then the clause's remaining @nonterm{expr}s are ignored, and
|
||||
evaluation continues with the next clause. The last clause can use
|
||||
@scheme[else] as a synonym for a @scheme[#t] test expression.
|
||||
|
||||
Using @scheme[cond], the @scheme[reply-more] procedure can be more
|
||||
clearly written as follows:
|
||||
|
|
|
@ -59,7 +59,7 @@ special characters or that might otherwise look like numbers.
|
|||
(string->symbol "6")
|
||||
]
|
||||
|
||||
@refdetails["mz:parse-symbol"]{the syntax of symbols}
|
||||
@refdetails/gory["mz:parse-symbol"]{the syntax of symbols}
|
||||
|
||||
The @scheme[display] form of a symbol is the same as the corresponding
|
||||
string.
|
||||
|
|
|
@ -183,7 +183,7 @@ Beware, however, that the REPL's printer recognizes the symbol
|
|||
]
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Lists and Scheme Syntax}
|
||||
@section[#:tag "guide:lists-and-syntax"]{Lists and Scheme Syntax}
|
||||
|
||||
Now that you know the truth about pairs and lists, and now that you've
|
||||
seen @scheme[quote], you're ready to understand the main way in which
|
||||
|
|
|
@ -16,7 +16,7 @@ expression. Also, a vector as an expression implicitly quotes the
|
|||
forms for its content, which means that identifiers and parenthesized
|
||||
forms in a vector constant represent symbols and lists.
|
||||
|
||||
@refdetails["mz:parse-vector"]{the syntax of vectors}
|
||||
@refdetails/gory["mz:parse-vector"]{the syntax of vectors}
|
||||
|
||||
@examples[
|
||||
(eval:alts #, @schemevalfont{#("a" "b" "c")} #("a" "b" "c"))
|
||||
|
|
|
@ -13,7 +13,7 @@ A @pidefterm{byte string} is a fixed-length arary of bytes. A
|
|||
@defterm{mutable} or @defterm{immutable}. When an immutable byte
|
||||
string is provided to a procedure like @scheme[bytes-set!], the
|
||||
@exnraise[exn:fail:contract]. Byte-string constants generated by the
|
||||
default reader (see @secref["parse-string"]) are immutable.
|
||||
default reader (see @secref["mz:parse-string"]) are immutable.
|
||||
|
||||
Two byte strings are @scheme[eq?] when mutating one would mutate the
|
||||
other. Two byte strings are @scheme[eqv?] and @scheme[equal?] when
|
||||
|
|
|
@ -7,3 +7,14 @@
|
|||
|
||||
A @pidefterm{character} corresponds to a Unicode scalar value (i.e., a
|
||||
Unicode code point that is not a surrogate).
|
||||
|
||||
@; ----------------------------------------
|
||||
@section{Classifications}
|
||||
|
||||
@defproc[(char-alphabetic? [char character?]) boolean?]{
|
||||
Returns @scheme[#t] if @scheme[char] is alphabetic...
|
||||
}
|
||||
|
||||
@defproc[(char-whitespace? [char character?]) boolean?]{
|
||||
Returns @scheme[#t] if @scheme[char] is whitespace...
|
||||
}
|
|
@ -34,14 +34,14 @@ is @scheme[#t] or @scheme[#f], @scheme[#f] otherwise.}
|
|||
@include-section["chars.scrbl"]
|
||||
|
||||
@; ------------------------------------------------------------
|
||||
@section[#:tag "symbols"]{Symbols}
|
||||
@section[#:tag "mz:symbols"]{Symbols}
|
||||
|
||||
@guideintro["guide:symbols"]{symbols}
|
||||
|
||||
A symbol is like an immutable string, but symbols are normally
|
||||
@index["interned symbols"]{@defterm{interned}}, so that two symbols
|
||||
with the same character content are normally @scheme[eq?]. All symbols
|
||||
produced by the default reader (see @secref["parse-symbol"]) are
|
||||
produced by the default reader (see @secref["mz:parse-symbol"]) are
|
||||
interned.
|
||||
|
||||
@index['("symbols" "generating")]{@index['("symbols" "unique")]{The}} two
|
||||
|
@ -54,8 +54,8 @@ Regular (interned) symbols are only weakly held by the internal symbol
|
|||
table. This weakness can never affect the result of an @scheme[eq?],
|
||||
@scheme[eqv?], or @scheme[equal?] test, but a symbol may disappear
|
||||
when placed into a weak box (see @secref["weakbox"]) used as the key
|
||||
in a weak hash table (see @secref["hashtable"]), or used as an
|
||||
ephemeron key (see @secref["ephemeron"]).
|
||||
in a weak hash table (see @secref["mz:hashtables"]), or used as an
|
||||
ephemeron key (see @secref["mz:ephemerons"]).
|
||||
|
||||
@defproc[(symbol? [v any/c]) boolean?]{Returns @scheme[#t] if @scheme[v] is
|
||||
a symbol, @scheme[#f] otherwise.}
|
||||
|
@ -190,13 +190,19 @@ If the @scheme[lst]s are empty, then @scheme[#f] is returned.}
|
|||
ignored.}
|
||||
|
||||
|
||||
@; ------------------------------------------------------------
|
||||
@section[#:tag "mz:vectors"]{Vectors}
|
||||
|
||||
@; ------------------------------------------------------------
|
||||
@section[#:tag "mz:boxes"]{Boxes}
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "hashtables"]{Hash Tables}
|
||||
@section[#:tag "mz:hashtables"]{Hash Tables}
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@include-section["sequences.scrbl"]
|
||||
|
||||
@section[#:tag "procedures"]{Procedures}
|
||||
@section[#:tag "mz:procedures"]{Procedures}
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "void"]{Void and Undefined}
|
||||
|
|
|
@ -1,211 +1,8 @@
|
|||
#reader(lib "docreader.ss" "scribble")
|
||||
@require["mz.ss"]
|
||||
|
||||
@interaction-eval[(require (lib "for.ss"))]
|
||||
@title[#:tag "mz:derived-syntax" #:style 'toc]{Derived Syntactic Forms}
|
||||
|
||||
@title[#:tag "mz:derived-syntax"]{Derived Syntactic Forms}
|
||||
|
||||
@section[#:tag "mz:for"]{Iterations and Comprehensions: @scheme[for], @scheme[for/list], ...}
|
||||
|
||||
@guideintro["guide:for"]{iterations and comprehensions}
|
||||
|
||||
@defform/subs[(for (for-clause ...) . body)
|
||||
([for-clause [id seq-expr]
|
||||
[(id ...) seq-expr]
|
||||
(code:line #:when guard-expr)])]{
|
||||
|
||||
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 one of its first two
|
||||
forms, where @scheme[[id seq-expr]] is a shorthand for @scheme[[(id
|
||||
...) seq-expr]]. In this simple 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 values of each
|
||||
element; the sequence produced by a @scheme[seq-expr] must return as
|
||||
many values for each iteration as corresponding @scheme[id]s.
|
||||
|
||||
The @scheme[id]s are then bound in the @scheme[body], which is
|
||||
evaluated, and whose results are ignored. Iteration continues with the
|
||||
next element in each sequence and with fresh locations for each
|
||||
@scheme[id].
|
||||
|
||||
A @scheme[for] form with zero @scheme[for-clause]s is equivalent to a
|
||||
single @scheme[for-clause] that binds an unreferenced @scheme[id] to
|
||||
a sequence containing a single element. All of the @scheme[id]s must
|
||||
be distinct according to @scheme[bound-identifier=?].
|
||||
|
||||
If any @scheme[for-clause] has the form @scheme[#: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 ([(i j) #hash(("a" . 1) ("b" . 20))])
|
||||
(display (list i j)))
|
||||
(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 results of the @scheme[fold/for] expression are the
|
||||
accumulator values.
|
||||
|
||||
@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/fold/derived orig-datum
|
||||
([accum-id init-expr] ...) (for-clause ...) . body)]{
|
||||
Like @scheme[fold/fold], but the extra @scheme[orig-datum] is used as the source for all syntax errors.
|
||||
}
|
||||
|
||||
@defform[(for*/fold/derived orig-datum
|
||||
([accum-id init-expr] ...) (for-clause ...) . body)]{
|
||||
Like @scheme[fold*/fold], but the extra @scheme[orig-datum] is used as the source for all syntax errors.
|
||||
}
|
||||
@local-table-of-contents[]
|
||||
|
||||
@include-section["for.scrbl"]
|
||||
|
|
281
collects/scribblings/reference/for.scrbl
Normal file
281
collects/scribblings/reference/for.scrbl
Normal file
|
@ -0,0 +1,281 @@
|
|||
#reader(lib "docreader.ss" "scribble")
|
||||
@require["mz.ss"]
|
||||
|
||||
@interaction-eval[(require (lib "for.ss"))]
|
||||
|
||||
@title[#:tag "mz:for"]{Iterations and Comprehensions: @scheme[for], @scheme[for/list], ...}
|
||||
|
||||
@guideintro["guide:for"]{iterations and comprehensions}
|
||||
|
||||
The PLT Scheme iteration forms are based on SRFI-42
|
||||
@cite[#:key "srfi-42"
|
||||
#:title "SRFI-42: Eager Comprehensions"
|
||||
#:author "Sebastian Egner"
|
||||
#:location "http://srfi.schemers.org/srfi-42/"
|
||||
#:date "2003"].
|
||||
|
||||
@section{Iteration and Comprehension Forms}
|
||||
|
||||
@defform/subs[(for (for-clause ...) . body)
|
||||
([for-clause [id seq-expr]
|
||||
[(id ...) seq-expr]
|
||||
(code:line #:when guard-expr)])]{
|
||||
|
||||
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 one of its first two
|
||||
forms, where @scheme[[id seq-expr]] is a shorthand for @scheme[[(id
|
||||
...) seq-expr]]. In this simple 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 values of each
|
||||
element; the sequence produced by a @scheme[seq-expr] must return as
|
||||
many values for each iteration as corresponding @scheme[id]s.
|
||||
|
||||
The @scheme[id]s are then bound in the @scheme[body], which is
|
||||
evaluated, and whose results are ignored. Iteration continues with the
|
||||
next element in each sequence and with fresh locations for each
|
||||
@scheme[id].
|
||||
|
||||
A @scheme[for] form with zero @scheme[for-clause]s is equivalent to a
|
||||
single @scheme[for-clause] that binds an unreferenced @scheme[id] to
|
||||
a sequence containing a single element. All of the @scheme[id]s must
|
||||
be distinct according to @scheme[bound-identifier=?].
|
||||
|
||||
If any @scheme[for-clause] has the form @scheme[#: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 ([(i j) #hash(("a" . 1) ("b" . 20))])
|
||||
(display (list i j)))
|
||||
(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 results of the @scheme[fold/for] expression are the
|
||||
accumulator values.
|
||||
|
||||
@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*].}
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Deriving New Iteration Forms}
|
||||
|
||||
@defform[(for/fold/derived orig-datum
|
||||
([accum-id init-expr] ...) (for-clause ...) . body)]{
|
||||
Like @scheme[fold/fold], but the extra @scheme[orig-datum] is used as the source for all syntax errors.
|
||||
}
|
||||
|
||||
@defform[(for*/fold/derived orig-datum
|
||||
([accum-id init-expr] ...) (for-clause ...) . body)]{
|
||||
Like @scheme[fold*/fold], but the extra @scheme[orig-datum] is used as the source for all syntax errors.
|
||||
}
|
||||
|
||||
@defform[(define-sequence-syntax id
|
||||
expr-transform-expr
|
||||
clause-transform-expr)]{
|
||||
|
||||
Defines @scheme[id] as syntax. An @scheme[(id . _rest)] form is
|
||||
treated specially when used to generate a sequence in a
|
||||
@scheme[_clause] of @scheme[for] (or one of its variants). In that
|
||||
case, the procedure result of @scheme[clause-transform-expr] is called
|
||||
to transform the clause.
|
||||
|
||||
When @scheme[id] is used in any other expression position, the result
|
||||
of @scheme[expr-transform-expr] is used; if it is an identifier
|
||||
@scheme[_other-id], then any use of @scheme[id] is converted to a use
|
||||
of @scheme[_other-id]; otherwise,@scheme[expr-transform-expr] must
|
||||
produce a procedure that is used as a macro transformer.
|
||||
|
||||
|
||||
When the @scheme[clause-transform-expr] transformer is used, it is
|
||||
given a @scheme[_clause] as an argument, where the clause's form is
|
||||
normalized so that the left-hand side is a parenthesized sequence of
|
||||
identifiers. The right-hand side is of the form @scheme[(id . _rest)].
|
||||
The result can be either @scheme[#f], to indicate that the forms
|
||||
should not be treated specially (perhaps because the number of bound
|
||||
identifiers is inconsistent with the @scheme[(id . _rest)] form), or a
|
||||
new @scheme[_clause] to to replace the given one. The new clause might
|
||||
use @scheme[:do-in].}
|
||||
|
||||
@defform[(:do-in ([(outer-id ...) outer-expr] ...)
|
||||
outer-check
|
||||
([loop-id loop-expr] ...)
|
||||
pos-guard
|
||||
([(inner-id ...) inner-expr] ...)
|
||||
pre-guard
|
||||
post-guard
|
||||
(loop-arg ...))]{
|
||||
|
||||
A form that can only be used as a @scheme[_seq-expr] in a
|
||||
@scheme[_clause] of @scheme[for] (or one of its variants).
|
||||
|
||||
Within a @scheme[for], the pieces of the @scheme[:do-in] form are
|
||||
spliced into the iteration essentially as follows:
|
||||
|
||||
@schemeblock[
|
||||
(let-values ([(outer-id ...) outer-expr] ...)
|
||||
outer-check
|
||||
(let loop ([loop-id loop-expr] ...)
|
||||
(if pos-guard
|
||||
(let-values ([(inner-id ...) inner-expr] ...)
|
||||
(if pre-guard
|
||||
(let _body-bindings
|
||||
(loop loop-arg ...))
|
||||
_done-expr))
|
||||
_done-expr)))
|
||||
]
|
||||
|
||||
where @scheme[_body-bindings] and @scheme[_done-expr] are from the
|
||||
context of the @scheme[:do-in] use. The actual @scheme[loop] binding
|
||||
and call has additional loop arguments to support iterations in
|
||||
parallel with the @scheme[:do-in] form, and the other pieces are
|
||||
similarly accompanied by pieces form parallel iterations.}
|
|
@ -101,6 +101,10 @@ possible contexts are as follows:
|
|||
|
||||
}
|
||||
|
||||
@section[#:tag "mz:intdef-body"]{Internal Definitions}
|
||||
|
||||
@section{Fully Expanded Programs}
|
||||
|
||||
A fully expanded program---that is, a parsed program---is represented
|
||||
in the same way as an unparsed program: as a syntax-wrapped
|
||||
combination of symbols, pairs, and other values. However, a fully
|
||||
|
|
|
@ -188,13 +188,13 @@ noted above). Two numbers are @scheme[equal?] when they are
|
|||
@examples[(/ 3 4) (/ 81 3 3) (/ 10.0) (/ 1+2i 3+4i)]
|
||||
|
||||
|
||||
@defproc[(quotient [n integer?] [m integer?]) number?]{ Returns
|
||||
@defproc[(quotient [n integer?] [m integer?]) integer?]{ Returns
|
||||
@scheme[(truncate (/ n m))].}
|
||||
|
||||
@examples[(quotient 10 3) (quotient -10.0 3) (quotient +inf.0 3)]
|
||||
|
||||
|
||||
@defproc[(remainder [n integer?] [m integer?]) number?]{ Returns
|
||||
@defproc[(remainder [n integer?] [m integer?]) integer?]{ Returns
|
||||
@scheme[q] with the same sign as @scheme[n] such that
|
||||
|
||||
@itemize{
|
||||
|
@ -208,6 +208,15 @@ noted above). Two numbers are @scheme[equal?] when they are
|
|||
@examples[(remainder 10 3) (remainder -10.0 3) (remainder 10.0 -3) (remainder -10 -3) (remainder +inf.0 3)]}
|
||||
|
||||
|
||||
@defproc[(quotient/remainder [n integer?] [m integer?]) (values number? number?)]{ Returns
|
||||
@scheme[(values (quotient n m) (remainder n m))], but the combination is computed
|
||||
more efficiently than separate calls to @scheme[quotient] and @scheme[remainder].
|
||||
|
||||
@examples[
|
||||
(quotient/remainder 10 3)
|
||||
]}
|
||||
|
||||
|
||||
@defproc[(modulo [n integer?] [m integer?]) number?]{ Returns
|
||||
@scheme[q] with the same sign as @scheme[m] where
|
||||
|
||||
|
@ -534,7 +543,7 @@ noted above). Two numbers are @scheme[equal?] when they are
|
|||
|
||||
@defproc[(string->number [s string?] [radix (exact-integer-in/c 2 16)
|
||||
10]) (or/c number? false/c)]{ Reads and returns a number datum from
|
||||
@scheme[s] (see @secref["parse-number"]), returning @scheme[#f] if
|
||||
@scheme[s] (see @secref["mz:parse-number"]), returning @scheme[#f] if
|
||||
@scheme[s] does not parse exactly as a number datum (with no
|
||||
whitespace). The optional @scheme[radix] argument specifies the default
|
||||
base for the number, which can be overriden by @litchar{#b},
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
@title[#:tag "mz:reader"]{Reading}
|
||||
|
||||
Scheme's reader is a recursive-descent parser that can be configured
|
||||
through a @seclink["readtable"]{readtable} and various other
|
||||
through a @seclink["mz:readtables"]{readtable} and various other
|
||||
@seclink["parameters"]{parameters}. This section describes the reader's
|
||||
parsing when using the default readtable.
|
||||
|
||||
|
@ -37,10 +37,10 @@ reader's behavior in @scheme[read] mode, and @scheme[read-syntax] mode
|
|||
does the same modulo wrapping the final result.
|
||||
|
||||
Reading is defined in terms of Unicode characters; see
|
||||
@secref["unicode"] for information on how a byte stream is converted
|
||||
@secref["mz:char-input"] for information on how a byte stream is converted
|
||||
to a character stream.
|
||||
|
||||
@section{Delimiters and Dispatch}
|
||||
@section[#:tag "mz:default-readtable-dispatch"]{Delimiters and Dispatch}
|
||||
|
||||
Along with @schemelink[char-whitespace?]{whitespace}, the following
|
||||
characters are @defterm{delimiters}:
|
||||
|
@ -286,7 +286,7 @@ input syntax for the boolean constant false.
|
|||
|
||||
When the reader encounters a @as-index{@litchar{(}},
|
||||
@as-index{@litchar["["]}, or @as-index{@litchar["{"]}, it starts
|
||||
parsing a pair or list; see @secref["pairs"] for information on pairs
|
||||
parsing a pair or list; see @secref["mz:pairs"] for information on pairs
|
||||
and lists.
|
||||
|
||||
To parse the pair or list, the reader recursively reads data
|
||||
|
@ -720,3 +720,11 @@ information on special-comment results and recursive reads.
|
|||
If the @scheme[read-accept-reader] parameter is set to @scheme[#f],
|
||||
then if the reader encounters @litchar{#reader}, the
|
||||
@exnraise[exn:fail:read].
|
||||
|
||||
@section[#:tag "mz:readtables"]{Readtables}
|
||||
|
||||
The dispatch table in @secref["mz:default-readtable-dispatch"]
|
||||
corresponds to the default @idefterm{readtable}.
|
||||
|
||||
@section[#:tag "mz:parse-honu"]{Honu Parsing}
|
||||
|
||||
|
|
|
@ -18,4 +18,20 @@ language.
|
|||
@include-section["derived.scrbl"]
|
||||
@include-section["data.scrbl"]
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
|
||||
@section["Input and Output"]
|
||||
|
||||
@subsection[#:tag "mz:char-input"]{Form Bytes to Characters}
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
|
||||
@section{Platform-Specific Path Conventions}
|
||||
|
||||
@subsection[#:tag "mz:unix-path"]{Unix and Mac OS X Paths}
|
||||
|
||||
@subsection[#:tag "mz:windows-path"]{Windows Paths}
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
|
||||
@index-section["mzscheme-index"]
|
||||
|
|
|
@ -3,16 +3,16 @@
|
|||
|
||||
@title[#:tag "mz:strings"]{Strings}
|
||||
|
||||
@guideintro["guide:string"]{strings}
|
||||
@guideintro["guide:strings"]{strings}
|
||||
|
||||
A @pidefterm{string} is a fixed-length arary of
|
||||
@seclink["characters"]{characters}.
|
||||
@seclink["mz:characters"]{characters}.
|
||||
|
||||
@index['("strings" "immutable")]{A} string can be @defterm{mutable} or
|
||||
@defterm{immutable}. When an immutable string is provided to a
|
||||
procedure like @scheme[string-set!], the
|
||||
@exnraise[exn:fail:contract]. String constants generated by the
|
||||
default reader (see @secref["parse-string"]) are
|
||||
default reader (see @secref["mz:parse-string"]) are
|
||||
immutable.
|
||||
|
||||
Two strings are @scheme[eq?] when mutating one would mutate the other.
|
||||
|
|
|
@ -27,9 +27,6 @@ Within such specifications,
|
|||
@item{@scheme[...+] indicates one or
|
||||
more repetitions of the preceding datum.}
|
||||
|
||||
@item{@scheme[?] means zero instances or one instance
|
||||
of the preceding datum.}
|
||||
|
||||
@item{italic meta-identifier play the role of non-terminals; in
|
||||
particular,
|
||||
|
||||
|
@ -48,7 +45,7 @@ Within such specifications,
|
|||
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).}
|
||||
@secref["mz:intdef-body"] for details).}
|
||||
|
||||
}} }
|
||||
|
||||
|
@ -230,7 +227,7 @@ a sequence of @scheme[_formal-arg]s optionally ending with a
|
|||
list that is associated to @scheme[rest-id].}
|
||||
|
||||
The @scheme[formals*] identifiers are bound in the @scheme[body]. (See
|
||||
@secref["intdef-body"] for information on @scheme[body] forms.) When
|
||||
@secref["mz: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.
|
||||
|
@ -299,7 +296,7 @@ support keyword and optional arguments.
|
|||
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
|
||||
@scheme[id]s are bound. (See @secref["mz: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=?].
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
Version 370.3
|
||||
|
||||
Fixed (get-face-list 'mono) for Mac OS X and X11
|
||||
Changed begin-container-sequence to delay making windows visible
|
||||
|
||||
|
||||
Version 370.2
|
||||
|
||||
Added 'no-focus style for canvas%
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Version 370.2
|
||||
Version 370.3
|
||||
Added hash-table-iterate-{first,next,key,value}
|
||||
|
||||
Version 370.2
|
||||
|
|
Loading…
Reference in New Issue
Block a user