work on docs for keyword arguments

svn: r6581
This commit is contained in:
Matthew Flatt 2007-06-12 01:44:02 +00:00
parent 0a7e47e495
commit 05607ad661
16 changed files with 401 additions and 136 deletions

View File

@ -25,6 +25,8 @@
opt-lambda
define-opt
keyword-apply
make-keyword-procedure
local
recur
@ -192,6 +194,34 @@
(define id (opt-lambda args body1 body ...))]
[(_ . rest) (define . rest)]))
(define (keyword-apply f kw-args normal-args . normal-argss)
(apply f (append (apply append
(map (lambda (p) (list (car p) (cdr p))) kw-args))
(if (null? normal-argss)
normal-args
(cons normal-args
(let loop ([normal-argss normal-argss])
(if (null? (cdr normal-argss))
(car normal-argss)
(cons (car normal-argss)
(loop (cdr normal-argss))))))))))
(define (make-keyword-procedure f)
(lambda args
(let loop ([args args]
[normal null]
[kw null])
(cond
[(null? args) (apply f kw (reverse normal))]
[(and (keyword? (car args))
(pair? (cdr args)))
(loop (cddr args)
normal
(cons (cons (car args) (cadr args)) kw))]
[else (loop (cdr args)
(cons (car args) normal)
kw)]))))
(define (sort-kws len need-kw l)
(for-each (lambda (kw)
(unless (memq kw l)

View File

@ -96,7 +96,7 @@
(make-element 'subscript (decode-content str)))
(define/kw (superscript #:body str)
(make-element superscript (decode-content str)))
(make-element 'superscript (decode-content str)))
;; ----------------------------------------

View File

@ -92,7 +92,7 @@
(provide onscreen menuitem defterm
schemefont schemevalfont schemeresultfont schemeidfont
schemeparenfont schemekeywordfont
schemeparenfont schemekeywordfont schememetafont
file exec
link procedure
idefterm)
@ -116,6 +116,8 @@
(make-element "schemesymbol" (decode-content str)))
(define/kw (schemeparenfont #:body str)
(make-element "schemeparen" (decode-content str)))
(define/kw (schememetafont #:body str)
(make-element "schememeta" (decode-content str)))
(define/kw (schemekeywordfont #:body str)
(make-element "schemekeyword" (decode-content str)))
(define/kw (file #:body str)
@ -161,9 +163,9 @@
(schemeresultfont "#<undefined>"))
(define dots0
(make-element "schemeparen" (list "...")))
(make-element "schememeta" (list "...")))
(define dots1
(make-element "schemeparen" (list "..." (superscript "+"))))
(make-element "schememeta" (list "...+")))
(define-syntax (arg-contract stx)
(syntax-case stx (... ...+)
@ -322,7 +324,7 @@
(if (keyword? (car i))
(cadr i)
(car i))))
(apply append (map cdr prototypes)))])
(apply append (map cdr prototypes)))])
(make-splice
(cons
(make-table
@ -437,21 +439,22 @@
(make-paragraph
(list
(to-element
`(struct ,(make-target-element*
(to-element name)
(let ([name (if (pair? name)
(car name)
name)])
(list* (list name)
(list name '?)
(list 'make- name)
(append
(map (lambda (f)
(list name '- (car f)))
fields)
(map (lambda (f)
(list 'set- name '- (car f) '!))
fields)))))
`(,(schemeparenfont "struct")
,(make-target-element*
(to-element name)
(let ([name (if (pair? name)
(car name)
name)])
(list* (list name)
(list name '?)
(list 'make- name)
(append
(map (lambda (f)
(list name '- (car f)))
fields)
(map (lambda (f)
(list 'set- name '- (car f) '!))
fields)))))
,(map car fields))))))))
(map (lambda (v)
(cond
@ -506,7 +509,8 @@
[(pair? form) (append (loop (car form))
(loop (cdr form)))]
[else null])))
forms))])
forms))]
[current-meta-list '(... ...+)])
(make-splice
(cons
(make-table
@ -550,7 +554,8 @@
[(pair? form) (append (loop (car form))
(loop (cdr form)))]
[else null]))
(current-variable-list))])
(current-variable-list))]
[current-meta-list '(... ...+)])
(make-blockquote
"leftindent"
(cons

View File

@ -15,14 +15,16 @@
syntax-ize-hook
current-keyword-list
current-variable-list
current-meta-list
(struct shaped-parens (val shape)))
(define no-color "schemeplain")
(define meta-color "schemeplain")
(define reader-color "schemeplain")
(define keyword-color "schemekeyword")
(define comment-color "schemecomment")
(define paren-color "schemeparen")
(define meta-color "schememeta")
(define value-color "schemevalue")
(define symbol-color "schemesymbol")
(define variable-color "schemevariable")
@ -39,6 +41,8 @@
set!)))
(define current-variable-list
(make-parameter null))
(define current-meta-list
(make-parameter null))
(define defined-names (make-hash-table))
@ -246,7 +250,7 @@
[(unsyntax) (values "#," 0)])])
(out str (if (positive? (+ quote-depth quote-delta))
value-color
meta-color))
reader-color))
(let ([i (cadr (syntax->list c))])
(set! src-col (or (syntax-column i) src-col))
(hash-table-put! next-col-map src-col dest-col)
@ -339,8 +343,6 @@
(char=? (string-ref s 0) #\_))
(values (substring s 1) #t #f)
(values s #f #f))))]
[(is-kw?) (and (identifier? c)
(memq (syntax-e c) (current-keyword-list)))]
[(is-var?) (and (identifier? c)
(memq (syntax-e c) (current-variable-list)))])
(if (element? (syntax-e c))
@ -375,8 +377,12 @@
value-color]
[(identifier? c)
(cond
[is-kw?
[(and (identifier? c)
(memq (syntax-e c) (current-keyword-list)))
keyword-color]
[(and (identifier? c)
(memq (syntax-e c) (current-meta-list)))
meta-color]
[is-var?
variable-color]
[it? variable-color]
@ -526,7 +532,9 @@
(list #f 1 col (+ 1 col)
(+ 2
vec-sz
(sub1 (length l))
(if (zero? (length l))
0
(sub1 (length l)))
(apply + (map syntax-span l)))))))]
[(pair? v)
(let* ([a (syntax-ize (car v) (+ col 1))]

View File

@ -165,6 +165,11 @@
font-family: Courier; font-size: 80%;
}
.schememeta {
color: #262680;
font-family: Courier; font-size: 80%;
}
.schemeopt {
color: black;
}

View File

@ -37,13 +37,15 @@ procedure's @idefterm{arity} is the number(s) of arguments that it
accepts.
@;------------------------------------------------------------------------
@section{Keyword Arguments}
@section[#:tag "guide:keyword-args"]{Keyword Arguments}
Some procedures accept @defterm{keyword arguments} in addition to
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]:
@margin-note{For an introduction to keywords, see @secref["guide:keywords"].}
@specform/subs[
(_proc-expr _arg ...)
([arg arg-expr
@ -55,23 +57,24 @@ 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
by-position argument, and with @scheme['fast] as an argument
associated with the @scheme[#:mode] keyword. 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.
is a syntax error. The @scheme[#:mode] keyword must be followed by an
expression to produce an argument value, and @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
@scheme[_arg-expr]s are evaluated, but a procedure accepts keyword
arguments independent of their position in the argument list. The
above call to @scheme[go] can be equivalently written
@schemeblock[(go #:mode #:fast "super.ss")]
@schemeblock[(go #:mode 'fast "super.ss")]
@refdetails["mz:application"]{procedure applications}
@ -98,8 +101,8 @@ of the items in the list:
(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
The @scheme[apply] procedure offers a way around this restriction. It
takes a procedure and a @italic{list} arguments, and it applies the
procedure to the arguments:
@def+int[
@ -109,3 +112,26 @@ procedure to the arguments:
(avg '(1 2))
(avg '(1 2 3 4))
]
As a convenience, the @scheme[apply] produce accepts additional
arguments between the procedure and the list. The additional arguments
are effectively @scheme[cons]ed onto the argument list:
@def+int[
(define (anti-sum lst)
(apply - 0 lst))
(anti-sum '(1 2 3))
]
The @scheme[apply] procedure supports only by-position arguments. To
apply a procedure with keyword arguments, use the
@scheme[keyword-apply] procedure, which accepts a procedure to apply
and two lists. The first list contains contains pairs, each matching a
keyword with its corresponding value. The second list contains
by-position procedure arguments, as for @scheme[apply].
@schemeblock[
(keyword-apply go
(list (cons '#:mode 'fast))
(list "super.ss"))
]

View File

@ -23,5 +23,6 @@ built-in datatypes for simple forms of data.
@include-section["boxes.scrbl"]
@include-section["hash-tables.scrbl"]
@include-section["paths.scrbl"]
@include-section["regexps-data.scrbl"]
@include-section["keywords.scrbl"]
@include-section["void-and-undef.scrbl"]

View File

@ -5,7 +5,7 @@
@interaction-eval[(require (rename (lib "etc.ss") define define-opt))]
@title{Definitions: @scheme[define] and @scheme[define-values]}
@title{Definitions: @scheme[define]}
A basic definition has the form
@ -65,7 +65,7 @@ which is a shorthand
]
@;------------------------------------------------------------------------
@section[#:tag "guide:multiple-values"]{Multiple Values}
@section[#:tag "guide:multiple-values"]{Multiple Values and @scheme[define-values]}
A Scheme expression normally produces a single result, but some
expressions can produce multiple results. For example,
@ -78,7 +78,7 @@ but @scheme[quotient/remainder] produces the same two values at once:
(quotient/remainder 13 3)
]
As shown abpve, the REPL prints each result value on its own line.
As shown above, 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

View File

@ -51,10 +51,10 @@ 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.
A @schememetafont{...} indicates zero or more repetitions of the
preceding form, and @schememetafont{...+} 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}:

View File

@ -3,10 +3,11 @@
@require[(lib "eval.ss" "scribble")]
@require["guide-utils.ss"]
@title[#:tag "keywords"]{Keywords}
@title[#:tag "guide:keywords"]{Keywords}
A @defterm{keyword} is similar to a symbol (see @secref["guide:symbols"]),
but its printed form is prefixed with @litchar{#:}.
A @defterm{keyword} value is similar to a symbol (see
@secref["guide:symbols"]), but its printed form is prefixed with
@litchar{#:}.
@refdetails/gory["mz:parse-keyword"]{the syntax of keywords}
@ -16,17 +17,22 @@ but its printed form is prefixed with @litchar{#:}.
(eq? '#:apple (string->keyword "apple"))
]
Although keywords are values, an unquoted keyword is not an
expression, just as an unquoted identifier does not produce a symbol:
More precisely, a keyword is analogous to an identifier; in the same
way that an identifier can be quoted to produce a symbol, a keyword
can be quoted to produce a value. The same term ``keyword'' is used in
both cases, but we sometimes use @defterm{keyword value} to refer more
specifically to the result of a quote-keyword expression or of
@scheme[string->keyword]. An unquoted keyword is not an expression,
just as an unquoted identifier does not produce a symbol:
@examples[
not-a-symbol-expression
#:not-a-keyword-expression
]
Despite their similarities, keywords are used differently than
symbols. Keywords are intented for use (unquoted) as special markers
in argument lists and in certain syntactic forms.
Despite their similarities, keywords are used in a different way than
identifiers or symbols. Keywords are intented for use (unquoted) as
special markers in argument lists and in certain syntactic forms.
@italic{Need some examples here, once we have more keyword-based
procedures and syntax in place...}

View File

@ -4,10 +4,12 @@
@require["guide-utils.ss"]
@interaction-eval[(require (rename (lib "etc.ss") lambda opt-lambda))]
@interaction-eval[(require (only (lib "etc.ss") keyword-apply
make-keyword-procedure))]
@title[#:tag "guide:lambda"]{Procedures: @scheme[lambda] and @scheme[case-lambda]}
@title[#:tag "guide:lambda"]{Procedures: @scheme[lambda]}
A @scheme[lambda] expression creates a procedure. In the simplest
Such a @scheme[lambda] expression creates a procedure. In the simplest
case, a @scheme[lambda] expression has the form
@specform[
@ -28,7 +30,7 @@ A @scheme[lambda] form with @math{n} @scheme[_arg-id]s accepts
]
@;------------------------------------------------------------------------
@section{Rest Arguments}
@section{Declaring a Rest Argument}
A @scheme[lambda] expression can also have the form
@ -50,8 +52,8 @@ into a list bound to @scheme[_rest-id].
1 2 3)
]
Procedures of this form often use @scheme[apply] to call another
procedure that accepts any number of arguments.
Procedures with a @scheme[_rest-id] 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].}
@ -65,17 +67,17 @@ procedure that accepts any number of arguments.
(max-mag 1 -2 0)
]
Generalizing the fixed-arity and any-arity style, a @scheme[lambda]
expression can have the form
The @scheme[lambda] form also supports required arguments combined
with a @scheme[_rest-id]:
@specform[
(lambda (arg-id ...+ . rest-id)
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.
The result of this form is a procedure that requires at least as many
arguments as @scheme[_arg-id]s, and also accepts any number of
additional arguments.
@defexamples[
(define max-mag
@ -90,16 +92,19 @@ A @scheme[_rest-id] variable is sometimes called a @defterm{rest
argument}, because it accepts the ``rest'' of the procedure arguments.
@;------------------------------------------------------------------------
@section{Optional Arguments}
@section{Declaring Optional Arguments}
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:
@specform/subs[
(lambda (arg ...+ . rest-id)
(lambda gen-formals
body ...+)
([arg arg-id
([gen-formals (arg ...)
rest-id
(arg ...+ . rest-id)]
[arg arg-id
[arg-id default-expr]])
]{}
@ -129,15 +134,18 @@ and every following @scheme[_arg-id] must have a default as well.
(greet "Adam")
]
@section{Keyword Arguments}
@section[#:tag "guide:lambda-keywords"]{Declaring 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:
@margin-note{For an introduction to applications with keywords,
see @secref["guide:keyword-args"].}
@specform/subs[
(lambda (arg ...+ . rest-id)
(lambda gen-formals
body ...+)
([arg arg-id
[arg-id default-expr]
@ -145,7 +153,7 @@ for either kind of argument:
(code:line arg-keyword [arg-id default-expr])])
]{}
As argument specified as @scheme[(code:line _arg-keyword _arg-id)] is
An 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
@ -160,7 +168,7 @@ be matched to an argument value by keyword instead of by position.
(greet #:last "Doe" "John")
]
A @scheme[(code:line _arg-keyword [_arg-id _default-expr])] argument
An @scheme[(code:line _arg-keyword [_arg-id _default-expr])] argument
specifies a keyword-based argument with a default value.
@defexamples[
@ -174,6 +182,29 @@ specifies a keyword-based argument with a default value.
(greet "Karl" #:last "Marx" #:hi "Guten Tag")
]
The @scheme[lambda] form does not directly support the creation
of a procedure that accepts ``rest'' keywords. To construct a
procedure that accepts any and all keyword arguments, use
@scheme[make-keyword-procedure]. The procedure supplied to
@scheme[make-keyword-procedure] receives all keyword arguments as
a list of pairs through the first (by-position) argument, and
then all by-position arguments from an application as the
remaining by-position arguments.
@margin-note{For an introduction to @scheme[keyword-apply], see
@secref["guide:apply"].}
@defexamples[
(define (trace-wrap f)
(make-keyword-procedure
(lambda (kw-args . rest)
(printf "Called with ~s ~s\n" kw-args rest)
(keyword-apply f kw-args rest))))
((trace-wrap greet) "John" #:hi "Howdy")
]
@refdetails["mz:lambda"]{procedure expressions}
@;------------------------------------------------------------------------
@section{Arity-Sensitive Procedures: @scheme[case-lambda]}
@ -190,7 +221,7 @@ that are supplied. A case-lambda expression has the form
(arg-id ...+ . rest-id)])
]
where each @scheme[_formals _body ...+] is anlogous to @scheme[(lambda
where each @scheme[[_formals _body ...+]] is analogous 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.
@ -208,5 +239,3 @@ case that matches the number of given arguments.
A @scheme[case-lambda] procedure cannot directly support optional or
keyword arguments.
@refdetails["mz:lambda"]{procedure expressions}

View File

@ -3,7 +3,7 @@
@require[(lib "eval.ss" "scribble")]
@require["guide-utils.ss"]
@title[#:tag "paths"]{Paths}
@title[#:tag "guide:paths"]{Paths}
A @defterm{path} encapsulates a filesystem path that (potentially)
names a file or directory. Although paths can be converted to and from

View File

@ -0,0 +1,8 @@
#reader(lib "docreader.ss" "scribble")
@require[(lib "manual.ss" "scribble")]
@require[(lib "eval.ss" "scribble")]
@require["guide-utils.ss"]
@title[#:tag "guide:regexp-literals"]{Regexps}
A @defterm{regexp} is a pattern for regular-expression matching.

View File

@ -202,7 +202,8 @@ If the @scheme[lst]s are empty, then @scheme[#f] is returned.}
@; ----------------------------------------------------------------------
@include-section["sequences.scrbl"]
@section[#:tag "mz:procedures"]{Procedures}
@; ----------------------------------------------------------------------
@include-section["procedures.scrbl"]
@; ----------------------------------------------------------------------
@section[#:tag "void"]{Void and Undefined}

View File

@ -0,0 +1,149 @@
#reader(lib "docreader.ss" "scribble")
@require["mz.ss"]
@interaction-eval[(require (rename (lib "etc.ss") lambda opt-lambda))]
@interaction-eval[(require (only (lib "etc.ss") keyword-apply
make-keyword-procedure))]
@title[#:tag "mz:procedures"]{Procedures}
@defproc[(procedure? [v any/c]) boolean]{ Returns @scheme[#t] if
@scheme[v] is a procedure, @scheme[#f] otherwise.}
@defproc[(apply [proc procedure?] [v any/c] ... [lst list?]) any]{
@guideintro["guide:apply"]{@scheme[apply]}
Applies @scheme[proc] using the content of @scheme[(list* v ... lst)]
as the (by-position) arguments. The given @scheme[proc] must accept as
many arguments as the number of @scheme[v]s plus length of
@scheme[lst], and it must not require any keyword arguments;
otherwise, the @exnraise[exn:fail:contract]. The given @scheme[proc]
is called in tail position with respect to the @scheme[apply] call.
@examples[
(apply + '(1 2 3))
(apply + 1 2 '(3))
(apply + '())
]}
@defproc[(keyword-apply [proc procedure?]
[kw-lst (listof (cons/c keyword? any/c))]
[v any/c] ...
[lst list?])
any]{
@guideintro["guide:apply"]{@scheme[keyword-apply]}
Like @scheme[apply], but @scheme[kw-lst] supplies by-keyword arguments
in addition to the by-position arguments of the @scheme[v]s and
@scheme[lst]. The given @scheme[kw-lst] must be sorted using
@scheme[keyword<] on the @scheme[car] of each pair in the list, and no
keyword can appear twice in the @scheme[car]s of @scheme[kw-lst]. The
given @scheme[proc] must accept all of the keywords in
@scheme[kw-lst], and it must not require any other keywords;
otherwise, the @exnraise[exn:fail:contract].
@defexamples[
(define (f x #:y y #:z [z 10])
(list x y z))
(keyword-apply f '((#:y . 2)) '(1))
(keyword-apply f '((#:y . 2) (#:z . 3)) '(1))
]}
@defproc[(procedure-arity [proc procedure?])
(or/c exact-nonnegative-integer?
arity-at-least?
(listof
(or/c exact-nonnegative-integer?
arity-at-least?)))]{
Returns information about the number of arguments accepted by
@scheme[proc] when called without keyword arguments. The result
@scheme[_a] is one of the following:
@itemize{
@item{An exact non-negative integer, which means that the procedure
always accepts exactly @scheme[_a] arguments.}
@item{A @scheme[arity-at-least] instance, which means that the
procedure takes @scheme[(arity-at-least-value _a)] or more
arguments.}
@item{A list containing integers and @scheme[arity-at-least]
instances, which means that the procedure takes any number of
arguments that can match one of the elements of @scheme[_a].}
}
If a procedure requires at least one keyword argument, then
@scheme[procedure-arity] returns @scheme['()] for the procedure.
@examples[
(procedure-arity cons)
(procedure-arity list)
(arity-at-least? (procedure-arity list))
(arity-at-least-value (procedure-arity list))
(arity-at-least-value (procedure-arity (lambda (x . y) x)))
(procedure-arity (case-lambda [(x) 0] [(x y) 1]))
]}
@defproc[(procedure-arity-includes? [proc procedure?] [k exact-nonnegative-integer?])
boolean?]{
Returns @scheme[#t] if the procedure can accept @scheme[k] arguments
when no keyword arguments are supplied, @scheme[#f] otherwise.
@examples[
(procedure-arity-includes? cons 2)
(procedure-arity-includes? display 3)
]}
@defproc[(keyword-procedure-arity [proc procedure?])
(values
(listof keyword?)
(or/c (listof keyword?)
false/c)
(or/c
exact-nonnegative-integer?
arity-at-least?
(listof
(or/c
exact-nonnegative-integer?
arity-at-least?))))]{
Similar to @scheme[keyword-procedure-arity], but for the case
that keywords are supplied to @scheme[proc]. The first result is
a list of keywords (sorted by @scheme[keyword<]) that are
required when applying @scheme[proc]. The second result is a list
of accepted keyword (sorted by @scheme[keyword<]), or @scheme[#f]
to mean that any keyword is accepted. The last result is as for
@scheme[procedure-arity] for the by-position arguments of
@scheme[proc], except that it is not @scheme['()] when keywords
are required.}
@defproc[(make-keyword-procedure
[proc (((listof (cons/c keyword? any/c))) list? . ->* . any)])
procedure?]{
Returns a procedure that accepts any number of arguments and all
keyword arguments (without requiring any keyword arguments). The
resulting procedure calls @scheme[proc], supplying to @scheme[proc]
all keyword arguments given in the original application as a list of
keyword--value pairs, sorted by @scheme[keyword<] on the keywords. All
by-position arguments supplied in the original application are
supplied to @scheme[proc] after the list for keyword arguments.
@defexamples[
(define show
(make-keyword-procedure (lambda (kw-args . rest)
(list kw-args rest))))
(show 1)
(show #:init 0 1 2 3 #:extra 4)
]}
@defstruct[arity-at-least ([value nonnegative-exact-integer?])]{
This structure type is used for the result of @scheme[procedure-arity].}

View File

@ -27,25 +27,24 @@ Within such specifications,
@item{@scheme[...+] indicates one or
more repetitions of the preceding datum.}
@item{italic meta-identifier play the role of non-terminals; in
@item{italic meta-identifiers play the role of non-terminals; in
particular,
@itemize{
@item{a meta-identifier that ends in @scheme[_id] stands for a
syntax-wrapped symbol.}
@item{a meta-identifier that ends in @scheme[_id] stands for an
identifier.}
@item{a meta-identifier that ends in @scheme[_keyword] stands
for a syntax-wrapped keyword.}
for a keyword.}
@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["mz:intdef-body"] for details).}
@item{A meta-identifier that ends with @scheme[_body] stands
for a sub-form that is expanded in an
internal-definition context (see
@secref["mz:intdef-body"]).}
}} }
@ -149,21 +148,21 @@ according to their order in the application form.
@guideintro["guide:lambda"]{procedure expressions}
@defform/subs[(lambda formals* . body)
@defform/subs[(lambda gen-formals body ...+)
([formals (id ...)
(id ...+ . rest-id)
rest-id]
[formals* formals
(formal-arg ...)
(formal-arg ...+ . rest-id)]
[formal-arg id
[id default-expr]
(code:line keyword id)
(code:line keyword [id default-expr])])]{
[gen-formals formals
(arg ...)
(arg ...+ . rest-id)]
[arg id
[id default-expr]
(code:line keyword id)
(code:line keyword [id default-expr])])]{
Produces a procedure. The @scheme[formals*] determines the number of
Produces a procedure. The @scheme[gen-formals] determines the number of
arguments that the procedure accepts. It is either a simple
@scheme[_formals], or one of the extended forms.
@scheme[formals], or one of the extended forms.
A simple @scheme[_formals] has one of the following three forms:
@ -182,11 +181,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].}
Besides the three @scheme[_formals] forms, a @scheme[formals*] can be
a sequence of @scheme[_formal-arg]s optionally ending with a
Besides the three @scheme[formals] forms, a @scheme[gen-formals] can be
a sequence of @scheme[arg]s optionally ending with a
@scheme[rest-id]:
@specsubform[(formal-arg ...)]{ Each @scheme[formal-arg] has the following
@specsubform[(arg ...)]{ Each @scheme[arg] has the following
four forms:
@specsubform[id]{Adds one to both the minimum and maximum
@ -199,7 +198,7 @@ a sequence of @scheme[_formal-arg]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-arg] with a @scheme[default-expr] can appear
No @scheme[arg] with a @scheme[default-expr] can appear
before an @scheme[id] without a @scheme[default-expr] and
without a @scheme[keyword].}
@ -215,41 +214,40 @@ a sequence of @scheme[_formal-arg]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-arg] in
@scheme[formals*] does not matter, but each specified
The position of a @scheme[_keyword] @scheme[arg] in
@scheme[gen-formals] does not matter, but each specified
@scheme[_keyword] must be distinct.}
@specsubform[(formal-arg ...+ . rest-id)]{ Like the previous case, but
@specsubform[(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-arg]s, the extra arguments are placed into a
@scheme[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]. (See
@secref["mz:intdef-body"] for information on @scheme[body] forms.) When
The @scheme[gen-formals] identifiers are bound in the @scheme[body]s. 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] that is not one of the
identifiers in @scheme[formals*], then it refers to the same location
If any identifier appears in the @scheme[body]s that is not one of the
identifiers in @scheme[gen-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
When multiple identifiers appear in a @scheme[gen-formals], they must be
distinct according to @scheme[bound-identifier=?].
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
@scheme[gen-formals] includes @scheme[keyword]s and an application
includes too few arguments before the keyword section, the same
keyword in multiple positions, or a keyword that is not among the
@scheme[formals*] @scheme[_keyword]s, then the
@scheme[gen-formals] @scheme[_keyword]s, then the
@exnraise[exn:fail:contract].
The last expression in @scheme[body] is in tail position with respect
to the procedure body.
The last @scheme[body] expression is in tail position with respect to
the procedure body.
@examples[
((lambda (x) x) 10)
@ -260,9 +258,9 @@ to the procedure body.
(f #:arg 2 1)))
]}
@defform[(case-lambda [formals . body] ...)]{
@defform[(case-lambda [formals body ...+] ...)]{
Produces a procedure. Each @scheme[[forms 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
@ -271,7 +269,7 @@ procedure accepts the given number of arguments, the
@exnraise[exn:fail:contract].
Note that a @scheme[case-lambda] clause supports only
@scheme[formals], not the more general @scheme[_formals*] of
@scheme[formals], not the more general @scheme[_gen-formals] of
@scheme[lambda]. That is, @scheme[case-lambda] does not directly
support keyword and optional arguments.
@ -290,14 +288,13 @@ support keyword and optional arguments.
@;------------------------------------------------------------------------
@section{Local Binding: @scheme[let], @scheme[let*], and @scheme[letrec]}
@defform*[[(let ([id val-expr] ...) . body)
(let proc-id ([id init-expr] ...) . body)]]{
@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["mz:intdef-body"] for information
on @scheme[body] forms.) The last expression in @scheme[body] is in
locations. It then evaluates the @scheme[body]s, in which the
@scheme[id]s are bound. The last @scheme[body] expression is in
tail position with respect to the @scheme[let] form. The @scheme[id]s
must be distinct according to @scheme[bound-identifier=?].
@ -311,8 +308,8 @@ must be distinct according to @scheme[bound-identifier=?].
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.}
@scheme[(lambda (id ...) body ...+)], where @scheme[proc-id] is bound
within the @scheme[body]s to the procedure itself.}
@examples[
(let fac ([n 10])
@ -321,12 +318,12 @@ within @scheme[body] to the procedure itself.}
(* n (fac (sub1 n)))))
]
@defform[(let* ([id val-expr] ...) . body)]{
@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
availablek. The @scheme[id]s are bound in the remaining @scheme[val-expr]s
as well as the @scheme[body], and the @scheme[id]s need not be
as well as the @scheme[body]s, and the @scheme[id]s need not be
distinct.
@examples[
@ -335,12 +332,12 @@ distinct.
(list y x))
]}
@defform[(letrec ([id val-expr] ...) . body)]{
@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[id]s are bound in all @scheme[val-expr]s as well as the
@scheme[body]s. The @scheme[id]s must be distinct according to
@scheme[bound-identifier=?].
@examples[
@ -353,21 +350,21 @@ created first and filled with @|undefined-const|, and all
(is-odd? 11))
]}
@defform[(let-values ([(id ...) val-expr] ...) . body)]{ Like
@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].
for each @scheme[id], all of which are bound in the @scheme[body]s.
@examples[
(let-values ([(x y) (quotient/remainder 10 3)])
(list y x))
]}
@defform[(let*-values ([(id ...) val-expr] ...) . body)]{ Like
@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].
@scheme[val-expr]s and in the @scheme[body]s.
@examples[
(let*-values ([(x y) (quotient/remainder 10 3)]
@ -375,12 +372,12 @@ for each @scheme[id], all of which are bound in the later
z)
]}
@defform[(letrec-values ([(id ...) val-expr] ...) . body)]{ Like
@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].
and in the @scheme[body]s.
@examples[
(letrec-values ([(is-even? is-odd?)