doc work, and also generalize normalize-definition to work with opts and kws
svn: r6665
This commit is contained in:
parent
ea5b3493f3
commit
2e536dc70e
|
@ -34,6 +34,14 @@
|
|||
(substring s 0 (sub1 (string-length s))))
|
||||
sep)))
|
||||
|
||||
(define/public (strip-aux content)
|
||||
(cond
|
||||
[(null? content) null]
|
||||
[(aux-element? (car content))
|
||||
(strip-aux (cdr content))]
|
||||
[else (cons (car content)
|
||||
(strip-aux (cdr content)))]))
|
||||
|
||||
;; ----------------------------------------
|
||||
;; global-info collection
|
||||
|
||||
|
@ -218,7 +226,7 @@
|
|||
(null? (element-content i)))
|
||||
(let ([v (lookup part ht (link-element-tag i))])
|
||||
(if v
|
||||
(render-content (car v) part ht)
|
||||
(render-content (strip-aux (car v)) part ht)
|
||||
(render-content (list "[missing]") part ht)))]
|
||||
[(element? i)
|
||||
(render-content (element-content i) part ht)]
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
;; ----------------------------------------
|
||||
|
||||
(provide hspace
|
||||
elem
|
||||
elem aux-elem
|
||||
italic bold
|
||||
tt span-class
|
||||
subscript superscript)
|
||||
|
@ -80,6 +80,9 @@
|
|||
(define/kw (elem #:body str)
|
||||
(make-element #f (decode-content str)))
|
||||
|
||||
(define/kw (aux-elem #:body s)
|
||||
(make-aux-element #f (decode-content s)))
|
||||
|
||||
(define/kw (italic #:body str)
|
||||
(make-element 'italic (decode-content str)))
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
install-file
|
||||
get-dest-directory
|
||||
format-number
|
||||
strip-aux
|
||||
lookup)
|
||||
|
||||
(define/override (get-suffix) #".html")
|
||||
|
@ -71,7 +72,7 @@
|
|||
(content "text-html; charset=utf-8")))
|
||||
,@(let ([c (part-title-content d)])
|
||||
(if c
|
||||
`((title ,@(format-number number '(nbsp)) ,@(render-content c d ht)))
|
||||
`((title ,@(format-number number '(nbsp)) ,(content->string c this d ht)))
|
||||
null))
|
||||
(link ((rel "stylesheet")
|
||||
(type "text/css")
|
||||
|
@ -156,7 +157,7 @@
|
|||
`((class ,(element-style e)))
|
||||
null))
|
||||
,@(if (null? (element-content e))
|
||||
(render-content (cadr dest) part ht)
|
||||
(render-content (strip-aux (cadr dest)) part ht)
|
||||
(render-content (element-content e) part ht))))
|
||||
(begin (fprintf (current-error-port) "Undefined link: ~s~n" (link-element-tag e)) ; XXX Add source info
|
||||
`((font ((class "badlink"))
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
[(index-element element) ([tag tag?]
|
||||
[plain-seq (listof string?)]
|
||||
[entry-seq list?])]
|
||||
[(aux-element element) ()]
|
||||
;; specific renders support other elements, especially strings
|
||||
|
||||
[collected-info ([number (listof (or/c false/c integer?))]
|
||||
|
@ -132,13 +133,19 @@
|
|||
|
||||
(provide content->string)
|
||||
|
||||
(define (content->string c)
|
||||
(apply string-append
|
||||
(map (lambda (e)
|
||||
(element->string e))
|
||||
c)))
|
||||
(define content->string
|
||||
(case-lambda
|
||||
[(c) (c->s c element->string)]
|
||||
[(c renderer sec ht) (c->s c (lambda (e)
|
||||
(element->string e renderer sec ht)))]))
|
||||
|
||||
(define (element->string c)
|
||||
(define (c->s c do-elem)
|
||||
(apply string-append
|
||||
(map do-elem c)))
|
||||
|
||||
(define element->string
|
||||
(case-lambda
|
||||
[(c)
|
||||
(cond
|
||||
[(element? c) (content->string (element-content c))]
|
||||
[(string? c) c]
|
||||
|
@ -147,7 +154,14 @@
|
|||
[(ldquo rdquo) "\""]
|
||||
[(rsquo) "'"]
|
||||
[(rarr) "->"]
|
||||
[else (format "~s" c)])]))
|
||||
[else (format "~s" c)])])]
|
||||
[(c renderer sec ht)
|
||||
(cond
|
||||
[(element? c) (content->string (element-content c) renderer sec ht)]
|
||||
[(delayed-element? c)
|
||||
(content->string (force-delayed-element c renderer sec ht)
|
||||
renderer sec ht)]
|
||||
[else (element->string c)])]))
|
||||
|
||||
)
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
@require[(lib "eval.ss" "scribble")]
|
||||
@require["guide-utils.ss"]
|
||||
|
||||
@title[#:tag "guide:application"]{Procedure Applications}
|
||||
@title[#:tag "guide:application"]{Function Calls@aux-elem{ (Procedure Applications)}}
|
||||
|
||||
An expression of the form
|
||||
|
||||
|
@ -11,16 +11,18 @@ An expression of the form
|
|||
(_proc-expr _arg-expr ...)
|
||||
]
|
||||
|
||||
is a procedure application when @scheme[_proc-expr] is not an
|
||||
identifier that is bound as a transformer.
|
||||
is a function call---also known as a @defterm{procedure
|
||||
application}---when @scheme[_proc-expr] is not an identifier that is
|
||||
bound as a syntax transformer (such as @scheme[if] or
|
||||
@scheme[define]).
|
||||
|
||||
@section{Evaluation Order and Arity}
|
||||
|
||||
A procedure application is evaluated by first evaluating the
|
||||
A function call 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
|
||||
applied. Otherwise, an exception is raised.
|
||||
right). Then, if @scheme[_proc-expr] produced a function that accepts
|
||||
as many arguments as supplied @scheme[_arg-expr]s, the function is
|
||||
called. Otherwise, an exception is raised.
|
||||
|
||||
@examples[
|
||||
(cons 1 null)
|
||||
|
@ -29,17 +31,17 @@ applied. Otherwise, an exception is raised.
|
|||
(1 2 3)
|
||||
]
|
||||
|
||||
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
|
||||
Some functions, such as @scheme[cons], accept a fixed number of
|
||||
arguments. Some functions, such as @scheme[list], accept any number
|
||||
of arguments. Some functions accept a range of argument counts; for
|
||||
example @scheme[substring] accepts either two or three arguments. A
|
||||
procedure's @idefterm{arity} is the number(s) of arguments that it
|
||||
function's @idefterm{arity} is the number of arguments that it
|
||||
accepts.
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section[#:tag "guide:keyword-args"]{Keyword Arguments}
|
||||
|
||||
Some procedures accept @defterm{keyword arguments} in addition to
|
||||
Some functions 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]:
|
||||
|
@ -56,7 +58,7 @@ For example,
|
|||
|
||||
@schemeblock[(go "super.ss" #:mode 'fast)]
|
||||
|
||||
calls the procedure bound to @scheme[go] with @scheme["super.ss"] as a
|
||||
calls the function 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. A keyword is implicitly
|
||||
paired with the expression that follows it.
|
||||
|
@ -70,7 +72,7 @@ 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 keyword
|
||||
@scheme[_arg-expr]s are evaluated, but a function accepts keyword
|
||||
arguments independent of their position in the argument list. The
|
||||
above call to @scheme[go] can be equivalently written
|
||||
|
||||
|
@ -79,13 +81,12 @@ above call to @scheme[go] can be equivalently written
|
|||
@refdetails["mz:application"]{procedure applications}
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section[#:tag "guide:apply"]{The @scheme[apply] Procedure}
|
||||
@section[#:tag "guide:apply"]{The @scheme[apply] Function}
|
||||
|
||||
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:
|
||||
The syntax for function calls supports any number of arguments, but a
|
||||
specific call always specifies a fixed number of arguments. As a
|
||||
result, a function that takes a list of arguments cannot directly
|
||||
apply a function like @scheme[+] to all of the items in the list:
|
||||
|
||||
@def+int[
|
||||
(define (avg lst) (code:comment #, @elem{doesn't work...})
|
||||
|
@ -101,9 +102,9 @@ of the items in the list:
|
|||
(avg '(1 2))
|
||||
]
|
||||
|
||||
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:
|
||||
The @scheme[apply] function offers a way around this restriction. It
|
||||
takes a function and a @italic{list} arguments, and it applies the
|
||||
function to the arguments:
|
||||
|
||||
@def+int[
|
||||
(define (avg lst)
|
||||
|
@ -113,8 +114,8 @@ procedure to the arguments:
|
|||
(avg '(1 2 3 4))
|
||||
]
|
||||
|
||||
As a convenience, the @scheme[apply] procedure accepts additional
|
||||
arguments between the procedure and the list. The additional arguments
|
||||
As a convenience, the @scheme[apply] function accepts additional
|
||||
arguments between the function and the list. The additional arguments
|
||||
are effectively @scheme[cons]ed onto the argument list:
|
||||
|
||||
@def+int[
|
||||
|
@ -123,13 +124,13 @@ are effectively @scheme[cons]ed onto the argument list:
|
|||
(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
|
||||
The @scheme[apply] function supports only by-position arguments. To
|
||||
apply a function with keyword arguments, use the
|
||||
@scheme[keyword-apply] function, which accepts a function to apply
|
||||
and three lists. The first two lists are in parallel, where the first
|
||||
list contains keywords (sorted by @scheme[keyword<]), and the second
|
||||
list contains a corresponding argument for each keyword. The third
|
||||
list contains by-position procedure arguments, as for @scheme[apply].
|
||||
list contains by-position function arguments, as for @scheme[apply].
|
||||
|
||||
@schemeblock[
|
||||
(keyword-apply go
|
||||
|
|
|
@ -13,7 +13,7 @@ the language @schememodname[big], as in
|
|||
|
||||
means that, within the module, the identifiers described in this guide
|
||||
have the the meaning described here: @scheme[cons] refers to the
|
||||
procedure that creates a pair, @scheme[car] refers to the procedure
|
||||
function that creates a pair, @scheme[car] refers to the function
|
||||
that extracts the first element of a pair, and so on.
|
||||
|
||||
@margin-note{For information on the syntax of identifiers, see
|
||||
|
|
|
@ -18,11 +18,12 @@ built-in datatypes for simple forms of data.
|
|||
@include-section["char-strings.scrbl"]
|
||||
@include-section["byte-strings.scrbl"]
|
||||
@include-section["symbols.scrbl"]
|
||||
@include-section["keywords.scrbl"]
|
||||
@include-section["pairs.scrbl"]
|
||||
@include-section["vectors.scrbl"]
|
||||
@include-section["boxes.scrbl"]
|
||||
@include-section["hash-tables.scrbl"]
|
||||
@include-section["paths.scrbl"]
|
||||
@include-section["regexps-data.scrbl"]
|
||||
@include-section["keywords.scrbl"]
|
||||
@include-section["boxes.scrbl"]
|
||||
@include-section["void-and-undef.scrbl"]
|
||||
|
||||
@; @include-section["paths.scrbl"]
|
||||
@; @include-section["regexps-data.scrbl"]
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
@require[(lib "bnf.ss" "scribble")]
|
||||
@require["guide-utils.ss"]
|
||||
|
||||
@title{Programmer-Defined Datatypes}
|
||||
@title[#:tag "guide:define-struct"]{Programmer-Defined Datatypes}
|
||||
|
||||
This section introduces the @scheme[define-struct] form for creating
|
||||
your own datatypes. The class-based object system offers an alternate
|
||||
|
@ -33,20 +33,20 @@ We explain one use of the @scheme[_struct-id] binding in the next
|
|||
section.
|
||||
|
||||
In addition to defining @scheme[_struct-id], however,
|
||||
@scheme[define-struct] also defines a number of procedures whose names
|
||||
@scheme[define-struct] also defines a number of functions whose names
|
||||
are built from @scheme[_struct-id] and the @scheme[_field-id]s:
|
||||
|
||||
@itemize{
|
||||
|
||||
@item{@schemeidfont{make-}@scheme[_struct-id] : a
|
||||
@defterm{constructor} procedure that takes as many arguments as
|
||||
@defterm{constructor} function that takes as many arguments as
|
||||
the number of @scheme[_field-id]s, and returns an instance of
|
||||
the structure type.
|
||||
|
||||
@examples[(make-posn 1 2)]}
|
||||
|
||||
@item{@scheme[_struct-id]@schemeidfont{?} : a @defterm{predicate}
|
||||
procedure that takes a single argument and returns @scheme[#t]
|
||||
function that takes a single argument and returns @scheme[#t]
|
||||
if it is an instance of the structure type, @scheme[#f]
|
||||
otherwise.
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
@require[(lib "eval.ss" "scribble")]
|
||||
@require["guide-utils.ss"]
|
||||
|
||||
@interaction-eval[(require (lib "string.ss"))]
|
||||
|
||||
@title{Definitions: @scheme[define]}
|
||||
|
||||
A basic definition has the form
|
||||
|
@ -18,9 +20,9 @@ salutation
|
|||
]
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Procedure Shorthand}
|
||||
@section{Function Shorthand}
|
||||
|
||||
The @scheme[define] form also supports a shorthand for procedure
|
||||
The @scheme[define] form also supports a shorthand for function
|
||||
definitions:
|
||||
|
||||
@specform[(define (id arg ...) body ...+)]{}
|
||||
|
@ -45,8 +47,9 @@ which is a shorthand for
|
|||
(greet "John" "Doe")
|
||||
]
|
||||
|
||||
The procedure shorthand via @scheme[define] also supports a final
|
||||
argument to collect extra arguments in a list:
|
||||
The function shorthand via @scheme[define] also supports a ``rest''
|
||||
argument (i.e., a final argument to collect extra arguments in a
|
||||
list):
|
||||
|
||||
@specform[(define (id arg ... . rest-id) expr)]{}
|
||||
|
||||
|
@ -62,6 +65,65 @@ which is a shorthand
|
|||
(avg 1 2 3)
|
||||
]
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Curried Function Shorthand}
|
||||
|
||||
Consider the following @scheme[make-add-suffix] function that takes a
|
||||
string and returns another function that takes a string. Normally, the
|
||||
result of @scheme[make-add-suffix] would be sent to some other
|
||||
function, but it could be called directly, like this:
|
||||
|
||||
@def+int[
|
||||
(define make-add-suffix
|
||||
(lambda (s2)
|
||||
(lambda (s) (string-append s s2))))
|
||||
|
||||
((make-add-suffix "!") "hello")
|
||||
]
|
||||
|
||||
In a sense, the @scheme[make-add-suffix] function takes two arguments,
|
||||
but it takes them one at a time. A function that takes some of its
|
||||
arguments and returns a function to consume more is sometimes called a
|
||||
@defterm{curried function}.
|
||||
|
||||
Using the function-shorthand form of @scheme[define],
|
||||
@scheme[make-add-suffix] can be written equivalently as
|
||||
|
||||
@schemeblock[
|
||||
(define (make-add-suffix s2)
|
||||
(lambda (s) (string-append s s2)))
|
||||
]
|
||||
|
||||
This shorthand reflects the shape of the function call
|
||||
@scheme[(make-add-suffix "!")]. The @scheme[define] form further
|
||||
supports a shorthand for defining curried functions that reflects
|
||||
nested function calls:
|
||||
|
||||
@def+int[
|
||||
(define ((make-add-suffix s2) s)
|
||||
(string-append s s2))
|
||||
((make-add-suffix "!") "hello")
|
||||
]
|
||||
@defs+int[
|
||||
[(define louder (make-add-suffix "!"))
|
||||
(define less-sure (make-add-suffix "?"))]
|
||||
(less-sure "really")
|
||||
(louder "really")
|
||||
]
|
||||
|
||||
The full syntax of the function shorthand for @scheme[define] is as follows:
|
||||
|
||||
@specform/subs[(define (head args) body ...+)
|
||||
([head id
|
||||
(head args)]
|
||||
[args (code:line arg ...)
|
||||
(code:line arg ... #, @schemeparenfont{.} rest-id)])]{}
|
||||
|
||||
The expansion of this shorthand has one nested @scheme[lambda] form
|
||||
for each @scheme[_head] in the definition, where the innermost
|
||||
@scheme[_head] corresponds to the outermost @scheme[lambda].
|
||||
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section[#:tag "guide:multiple-values"]{Multiple Values and @scheme[define-values]}
|
||||
|
||||
|
@ -78,8 +140,8 @@ but @scheme[quotient/remainder] produces the same two values at once:
|
|||
|
||||
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
|
||||
Multiple-valued functions can be implemented in terms of the
|
||||
@scheme[values] function, which takes any number of values and
|
||||
returns them as the results:
|
||||
|
||||
@interaction[
|
||||
|
@ -87,8 +149,10 @@ returns them as the results:
|
|||
]
|
||||
@def+int[
|
||||
(define (split-name name)
|
||||
(let ([m (regexp-match #rx"^([^ ]*) (.*)$" name)])
|
||||
(values (list-ref m 1) (list-ref m 2))))
|
||||
(let ([parts (regexp-split " " name)])
|
||||
(if (= (length parts) 2)
|
||||
(values (list-ref parts 0) (list-ref parts 1))
|
||||
(error "not a <first> <last> name"))))
|
||||
(split-name "Adam Smith")
|
||||
]
|
||||
|
||||
|
@ -106,12 +170,74 @@ 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].
|
||||
A @scheme[define] form (that is not a function shorthand) is
|
||||
equivalent to a @scheme[define-values] form with a single @scheme[_id].
|
||||
|
||||
@refdetails["mz:define"]{definitions}
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@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.
|
||||
When the grammar for a syntactic form specifies @scheme[_body], then
|
||||
the corresponding form can be either a definition or an expression.
|
||||
A definition as a @scheme[_body] is an @defterm{internal definition}.
|
||||
|
||||
All internal definitions in a @scheme[_body] sequence must appear
|
||||
before any expression, and the last @scheme[_body] must be an
|
||||
expression.
|
||||
|
||||
For example, the syntax of @scheme[lambda] is
|
||||
|
||||
@specform[
|
||||
(lambda gen-formals
|
||||
body ...+)
|
||||
]
|
||||
|
||||
so the following are valid instances of the grammar:
|
||||
|
||||
@schemeblock[
|
||||
(lambda (f) (code:comment #, @elem{no definitions})
|
||||
(printf "running\n")
|
||||
(f 0))
|
||||
|
||||
(lambda (f) (code:comment #, @elem{one definition})
|
||||
(define (log-it what)
|
||||
(printf "~a\n"))
|
||||
(log-it "running")
|
||||
(f 0)
|
||||
(log-it "done"))
|
||||
|
||||
(lambda (f n) (code:comment #, @elem{two definitions})
|
||||
(define (call n)
|
||||
(if (zero? n)
|
||||
(log-it "done")
|
||||
(begin
|
||||
(log-it "running")
|
||||
(f 0)
|
||||
(call (- n 1)))))
|
||||
(define (log-it what)
|
||||
(printf "~a\n"))
|
||||
(call f n))
|
||||
]
|
||||
|
||||
Internal definitions in a particular @scheme[_body] sequence are
|
||||
mutually recursive; that is, any definition can refer to any other
|
||||
definition---as long as the reference isn't actually evaluated before
|
||||
its definition takes place. If a definition is referenced too early,
|
||||
the result is a special value @|undefined-const|.
|
||||
|
||||
@defexamples[
|
||||
(define (weird)
|
||||
(define x x)
|
||||
x)
|
||||
(weird)
|
||||
]
|
||||
|
||||
A sequence of internal definitions using just @scheme[define] is
|
||||
easily translated to an equivalent @scheme[letrec] form (as introduced
|
||||
in the next section). However, other definition forms can appear as a
|
||||
@scheme[_body], including @scheme[define-struct] (see
|
||||
@secref["guide:define-struct"]) or @scheme[define-syntax] (see
|
||||
@secref["guide:macros"]).
|
||||
|
||||
@refdetails/gory["mz:intdef-body"]{internal definitions}
|
||||
|
|
|
@ -58,7 +58,7 @@ see the kinds of sequence generators that make interesting examples.
|
|||
|
||||
@section[#:tag "guide:sequences"]{Sequence Constructors}
|
||||
|
||||
The @scheme[in-range] procedure generates a sequence of numbers, given
|
||||
The @scheme[in-range] function generates a sequence of numbers, given
|
||||
an optional starting number (which defaults to @scheme[0]), a number
|
||||
before which the sequences ends, and an optional step (which defaults
|
||||
to @scheme[1]).
|
||||
|
@ -76,7 +76,7 @@ to @scheme[1]).
|
|||
(printf " ~a " i))
|
||||
]
|
||||
|
||||
The @scheme[in-naturals] procedure is similar, except that the
|
||||
The @scheme[in-naturals] function is similar, except that the
|
||||
starting number must be an exact non-negative integer (which defaults
|
||||
to @scheme[0]), the step is always @scheme[1], and there is no upper
|
||||
limit. A @scheme[for] loop using just @scheme[in-naturals] will never
|
||||
|
@ -90,7 +90,7 @@ escapes.
|
|||
(display i)))
|
||||
]
|
||||
|
||||
The @scheme[stop-before] and @scheme[stop-after] procedures construct
|
||||
The @scheme[stop-before] and @scheme[stop-after] functions construct
|
||||
a new sequence given a sequence and a predicate. The new sequence is
|
||||
like the given sequence, but truncated either immediately before or
|
||||
immediately after the first element for which the predicate returns
|
||||
|
@ -341,7 +341,7 @@ multiple values for the results.
|
|||
|
||||
@section{Multiple-Valued Sequences}
|
||||
|
||||
In the same way that a procedure or expression can produce multiple
|
||||
In the same way that a function or expression can produce multiple
|
||||
values, individual iterations of a sequence can produce multiple
|
||||
elements. For example, a hash table as a sequence generates two
|
||||
values for each iteration: a key and a value.
|
||||
|
|
|
@ -42,7 +42,7 @@ convention implicitly defines the meaning of many meta-variables:
|
|||
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.}
|
||||
@scheme[_body] must be an expression; see also @secref["guide:intdefs"].}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ using @idefterm{contracts}.
|
|||
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "regexp"]{Regular-Expression Matching (Regexps)}
|
||||
@section[#:tag "regexp"]{Regular-Expression Matching@aux-elem{ (Regexps)}}
|
||||
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
@ -70,11 +70,11 @@ using @idefterm{contracts}.
|
|||
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "units"]{Higher-Order Modules (Units)}
|
||||
@section[#:tag "units"]{Units (Higher-Order Modules)}
|
||||
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "macros"]{Syntactic Extension (Modules and Macros)}
|
||||
@section[#:tag "guide:macros"]{Syntactic Extension@aux-elem{ (Modules and Macros)}}
|
||||
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
@ -101,7 +101,7 @@ using @idefterm{contracts}.
|
|||
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "ffi"]{Foreign-Function Interface (FFI)}
|
||||
@section[#:tag "ffi"]{Foreign-Function Interface@aux-elem{ (FFI)}}
|
||||
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
@ -109,7 +109,7 @@ using @idefterm{contracts}.
|
|||
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section[#:tag "gui"]{Graphical User Interfaces (GUIs)}
|
||||
@section[#:tag "gui"]{Graphical User Interfaces@aux-elem{ (GUIs)}}
|
||||
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
@require[(lib "eval.ss" "scribble")]
|
||||
@require["guide-utils.ss"]
|
||||
|
||||
@title[#:tag "guide:lambda"]{Procedures: @scheme[lambda]}
|
||||
@title[#:tag "guide:lambda"]{Functions@aux-elem{ (Procedures)}: @scheme[lambda]}
|
||||
|
||||
Such a @scheme[lambda] expression creates a procedure. In the simplest
|
||||
Such a @scheme[lambda] expression creates a function. In the simplest
|
||||
case, a @scheme[lambda] expression has the form
|
||||
|
||||
@specform[
|
||||
|
@ -37,7 +37,7 @@ A @scheme[lambda] expression can also have the form
|
|||
|
||||
That is, a @scheme[lambda] expression can have a single
|
||||
@scheme[_rest-id] that is not surrounded by parentheses. The resulting
|
||||
procedure accepts any number of arguments, and the arguments are put
|
||||
function accepts any number of arguments, and the arguments are put
|
||||
into a list bound to @scheme[_rest-id].
|
||||
|
||||
@examples[
|
||||
|
@ -48,8 +48,8 @@ into a list bound to @scheme[_rest-id].
|
|||
1 2 3)
|
||||
]
|
||||
|
||||
Procedures with a @scheme[_rest-id] often use @scheme[apply] to call
|
||||
another procedure that accepts any number of arguments.
|
||||
Functions with a @scheme[_rest-id] often use @scheme[apply] to call
|
||||
another function that accepts any number of arguments.
|
||||
|
||||
@margin-note{See @secref["guide:apply"] for more information on
|
||||
@scheme[apply].}
|
||||
|
@ -71,7 +71,7 @@ with a @scheme[_rest-id]:
|
|||
body ...+)
|
||||
]
|
||||
|
||||
The result of this form is a procedure that requires at least as many
|
||||
The result of this form is a function that requires at least as many
|
||||
arguments as @scheme[_arg-id]s, and also accepts any number of
|
||||
additional arguments.
|
||||
|
||||
|
@ -85,7 +85,7 @@ additional arguments.
|
|||
]
|
||||
|
||||
A @scheme[_rest-id] variable is sometimes called a @defterm{rest
|
||||
argument}, because it accepts the ``rest'' of the procedure arguments.
|
||||
argument}, because it accepts the ``rest'' of the function arguments.
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Declaring Optional Arguments}
|
||||
|
@ -179,9 +179,9 @@ specifies a keyword-based argument with a default value.
|
|||
]
|
||||
|
||||
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
|
||||
of a function that accepts ``rest'' keywords. To construct a
|
||||
function that accepts any and all keyword arguments, use
|
||||
@scheme[make-keyword-procedure]. The function supplied to
|
||||
@scheme[make-keyword-procedure] receives keyword arguments through
|
||||
parallel lists in the first two (by-position) arguments, and
|
||||
then all by-position arguments from an application as the
|
||||
|
@ -199,12 +199,12 @@ remaining by-position arguments.
|
|||
((trace-wrap greet) "John" #:hi "Howdy")
|
||||
]
|
||||
|
||||
@refdetails["mz:lambda"]{procedure expressions}
|
||||
@refdetails["mz:lambda"]{function expressions}
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section{Arity-Sensitive Procedures: @scheme[case-lambda]}
|
||||
@section{Arity-Sensitive Functions: @scheme[case-lambda]}
|
||||
|
||||
The @scheme[case-lambda] form creates a procedure that can have
|
||||
The @scheme[case-lambda] form creates a function that can have
|
||||
completely different behaviors depending on the number of arguments
|
||||
that are supplied. A case-lambda expression has the form
|
||||
|
||||
|
@ -218,7 +218,7 @@ that are supplied. A case-lambda expression has the form
|
|||
]
|
||||
|
||||
where each @scheme[[_formals _body ...+]] is analogous to @scheme[(lambda
|
||||
_formals _body ...+)]. Applying a procedure produced by
|
||||
_formals _body ...+)]. Applying a function produced by
|
||||
@scheme[case-lambda] is like applying a @scheme[lambda] for the first
|
||||
case that matches the number of given arguments.
|
||||
|
||||
|
@ -233,5 +233,5 @@ case that matches the number of given arguments.
|
|||
(greet)
|
||||
]
|
||||
|
||||
A @scheme[case-lambda] procedure cannot directly support optional or
|
||||
A @scheme[case-lambda] function cannot directly support optional or
|
||||
keyword arguments.
|
||||
|
|
|
@ -14,7 +14,7 @@ Scheme is a dialect of the language Lisp, whose name originally stood
|
|||
for ``LISt Processor.'' The built-in list datatype remains a prominent
|
||||
feature of the language.
|
||||
|
||||
The @scheme[list] procedure takes any number of values and returns
|
||||
The @scheme[list] function takes any number of values and returns
|
||||
a list containing the values:
|
||||
|
||||
@interaction[(list "red" "green" "blue")
|
||||
|
@ -29,7 +29,7 @@ parentheses are used for both expressions, such as @scheme[(list "red"
|
|||
DrScheme, parentheses for results are printed in blue, whereas
|
||||
parentheses for expressions are brown.
|
||||
|
||||
Many predefined procedures operate on lists. Here are a few examples:
|
||||
Many predefined functions operate on lists. Here are a few examples:
|
||||
|
||||
@interaction[
|
||||
(code:line (length (list "a" "b" "c")) (code:comment #, @t{count the elements}))
|
||||
|
@ -44,14 +44,14 @@ Many predefined procedures operate on lists. Here are a few examples:
|
|||
@section{Predefined List Loops}
|
||||
|
||||
In addition to simple operations like @scheme[append], Scheme includes
|
||||
procedures that iterate over the elements of a list. These iteration
|
||||
procedures play much the same role as @tt{for} in Java and other
|
||||
languages. The body of a Scheme iteration is packaged into a procedure
|
||||
functions that iterate over the elements of a list. These iteration
|
||||
functions play much the same role as @tt{for} in Java and other
|
||||
languages. The body of a Scheme iteration is packaged into a function
|
||||
to be applied to each element, so the @scheme[lambda] form becomes
|
||||
particularly handy in combination with iteration procedures.
|
||||
particularly handy in combination with iteration functions.
|
||||
|
||||
Different list-iteration procedures combine iteration results in
|
||||
different ways. The @scheme[map] procedure uses the per-element
|
||||
Different list-iteration functions combine iteration results in
|
||||
different ways. The @scheme[map] function uses the per-element
|
||||
results to create a new list:
|
||||
|
||||
@interaction[
|
||||
|
@ -61,7 +61,7 @@ results to create a new list:
|
|||
(list "peanuts" "popcorn" "crackerjack"))
|
||||
]
|
||||
|
||||
The @scheme[andmap] and @scheme[ormap] procedures combine the results
|
||||
The @scheme[andmap] and @scheme[ormap] functions combine the results
|
||||
by @scheme[and]ing or @scheme[or]ing:
|
||||
|
||||
@interaction[
|
||||
|
@ -70,7 +70,7 @@ by @scheme[and]ing or @scheme[or]ing:
|
|||
(ormap number? (list "a" "b" 6))
|
||||
]
|
||||
|
||||
The @scheme[filter] procedure keeps elements for which the body result
|
||||
The @scheme[filter] function keeps elements for which the body result
|
||||
is true, and discards elements for which it is @scheme[#f]:
|
||||
|
||||
@interaction[
|
||||
|
@ -79,8 +79,8 @@ is true, and discards elements for which it is @scheme[#f]:
|
|||
]
|
||||
|
||||
The @scheme[map], @scheme[andmap], @scheme[ormap], and @scheme[filter]
|
||||
procedures can all handle multiple lists, instead of just a single
|
||||
list. The lists must all have the same length, and the given procedure
|
||||
functions can all handle multiple lists, instead of just a single
|
||||
list. The lists must all have the same length, and the given function
|
||||
must accept one argument for each list:
|
||||
|
||||
@interaction[
|
||||
|
@ -89,9 +89,9 @@ must accept one argument for each list:
|
|||
(list 6 3 7))
|
||||
]
|
||||
|
||||
The @scheme[foldl] procedure generalizes some iteration procedures. It
|
||||
uses the per-element procedure to both process an element and combine
|
||||
it with the ``current'' value, so the per-element procedure takes an
|
||||
The @scheme[foldl] function generalizes some iteration functions. It
|
||||
uses the per-element function to both process an element and combine
|
||||
it with the ``current'' value, so the per-element function takes an
|
||||
extra first argument. Also, a starting ``current'' value must be
|
||||
provided before the lists:
|
||||
|
||||
|
@ -103,7 +103,7 @@ provided before the lists:
|
|||
]
|
||||
|
||||
Despite its generality, @scheme[foldl] is not as popular as the other
|
||||
procedures. One reason is that @scheme[map], @scheme[ormap],
|
||||
functions. One reason is that @scheme[map], @scheme[ormap],
|
||||
@scheme[andmap], and @scheme[filter] cover the most common kinds of
|
||||
list loops.
|
||||
|
||||
|
@ -115,7 +115,7 @@ are described in see @secref["guide:for"].
|
|||
@;------------------------------------------------------------------------
|
||||
@section{List Iteration from Scratch}
|
||||
|
||||
Although @scheme[map] and other iteration procedures predefined, they
|
||||
Although @scheme[map] and other iteration functions predefined, they
|
||||
are not primitive in any interesting sense. You can write equivalent
|
||||
iterations using a handful of list primitives.
|
||||
|
||||
|
@ -136,7 +136,7 @@ non-empty list are
|
|||
]
|
||||
|
||||
To create a new node for a linked list---that is, to add to the front
|
||||
of the list---use the @scheme[cons] procedure, which is short for
|
||||
of the list---use the @scheme[cons] function, which is short for
|
||||
``construct.'' To get an empty list to start with, use the
|
||||
@scheme[empty] constant:
|
||||
|
||||
|
@ -148,7 +148,7 @@ empty
|
|||
|
||||
To process a list, you need to be able to distinguish empty lists from
|
||||
non-empty lists, because @scheme[first] and @scheme[rest] work only on
|
||||
non-empty lists. The @scheme[empty?] procedure detects empty lists,
|
||||
non-empty lists. The @scheme[empty?] function detects empty lists,
|
||||
and @scheme[cons?] detects non-empty lists:
|
||||
|
||||
@interaction[
|
||||
|
@ -159,7 +159,7 @@ and @scheme[cons?] detects non-empty lists:
|
|||
]
|
||||
|
||||
With these pieces, you can write your own versions of the
|
||||
@scheme[length] procedure, @scheme[map] procedure, and more.
|
||||
@scheme[length] function, @scheme[map] function, and more.
|
||||
|
||||
@defexamples[
|
||||
(define (my-length lst)
|
||||
|
@ -182,7 +182,7 @@ If the derivation of the above definitions is mysterious to you,
|
|||
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
|
||||
Both the @scheme[my-length] and @scheme[my-map] functions run in
|
||||
@math{O(n)} time for a list of length @math{n}. This is easy to see by
|
||||
imagining how @scheme[(my-length (list "a" "b" "c"))] must evaluate:
|
||||
|
||||
|
@ -202,14 +202,14 @@ For a list with @math{n} elements, evalution will stack up @math{n}
|
|||
list is exhausted.
|
||||
|
||||
You can avoid piling up additions by adding along the way. To
|
||||
accumulate a length this way, we need a procedure that takes both a
|
||||
accumulate a length this way, we need a function that takes both a
|
||||
list and the length of the list seem so far; the code below uses a
|
||||
local procedure @scheme[iter] that accumulates the length in an
|
||||
local function @scheme[iter] that accumulates the length in an
|
||||
argument @scheme[len]:
|
||||
|
||||
@schemeblock[
|
||||
(define (my-length lst)
|
||||
(code:comment #, @elem{local procedure @scheme[iter]:})
|
||||
(code:comment #, @elem{local function @scheme[iter]:})
|
||||
(define (iter lst len)
|
||||
(cond
|
||||
[(empty? lst) len]
|
||||
|
@ -231,8 +231,8 @@ Now evaluation looks like this:
|
|||
|
||||
The revised @scheme[my-length] runs in constant space, just as the
|
||||
evaluation steps above suggest. That is, when the result of a
|
||||
procedure call, like @scheme[(iter (list "b" "c") 1)], is exactly the
|
||||
result of some other procedure call, like @scheme[(iter (list "c")
|
||||
function call, like @scheme[(iter (list "b" "c") 1)], is exactly the
|
||||
result of some other function call, like @scheme[(iter (list "c")
|
||||
2)], then the first one doesn't have to wait around for the second
|
||||
one, because that takes up space for no good reason.
|
||||
|
||||
|
@ -265,7 +265,7 @@ It turns out that if you write
|
|||
(f i)))
|
||||
]
|
||||
|
||||
then the @scheme[for/list] form in the procedure both is expanded to
|
||||
then the @scheme[for/list] form in the function both is expanded to
|
||||
essentially the same code as the @scheme[iter] local definition and
|
||||
use. The difference is merely syntactic convenience.
|
||||
|
||||
|
@ -291,7 +291,7 @@ tail-recursive programs automatically run the same as a loop, lead
|
|||
Scheme programmers to embrace recursive forms rather than avoid them.
|
||||
|
||||
Suppose, for example, that you want to remove consecutive duplicates
|
||||
from a list. While such a procedure can be written as a loop that
|
||||
from a list. While such a function can be written as a loop that
|
||||
remembers the previous element for each iteration, a Scheme programmer
|
||||
would more likely just write the following:
|
||||
|
||||
|
@ -308,12 +308,12 @@ would more likely just write the following:
|
|||
(remove-dups (list "a" "b" "b" "b" "c" "c"))
|
||||
]
|
||||
|
||||
In general, this procedure consumes @math{O(n)} space for an input
|
||||
In general, this function consumes @math{O(n)} space for an input
|
||||
list of length @math{n}, but that's fine, since it produces an
|
||||
@math{O(n)} result. If the input list happens to be mostly consecutive
|
||||
duplicates, then the resulting list can be much smaller than
|
||||
@math{O(n)}---and @scheme[remove-dups] will also use much less than
|
||||
@math{O(n)} space! The reason is that when the procedure discards
|
||||
@math{O(n)} space! The reason is that when the function discards
|
||||
duplicates, it returns the result of a @scheme[remove-dups] call
|
||||
directly, so the tail-call ``optimization'' kicks in:
|
||||
|
||||
|
|
|
@ -25,9 +25,9 @@ is equivalent to
|
|||
(_proc-id _init-expr ...))
|
||||
]
|
||||
|
||||
That is, a named @scheme[let] binds a procedure identifier that is
|
||||
visible only in the procedure's body, and it implicitly calls the
|
||||
procedure with the values of some initial expressions.
|
||||
That is, a named @scheme[let] binds a function identifier that is
|
||||
visible only in the function's body, and it implicitly calls the
|
||||
function with the values of some initial expressions.
|
||||
|
||||
@defexamples[
|
||||
(define (duplicate pos lst)
|
||||
|
|
|
@ -68,23 +68,23 @@ binds @nonterm{id} to the result of @nonterm{expr}, while
|
|||
|
||||
@schemeblock[#, @fun-defn-stx]
|
||||
|
||||
binds the first @nonterm{id} to a procedure that takes
|
||||
arguments as named by the remaining @nonterm{id}s. In the
|
||||
procedure case, the @nonterm{expr}s are the body of the
|
||||
procedure. When the procedure is called, it returns the result of the
|
||||
last @nonterm{expr}.
|
||||
binds the first @nonterm{id} to a function (also called a
|
||||
@defterm{procedure}) that takes arguments as named by the remaining
|
||||
@nonterm{id}s. In the function case, the @nonterm{expr}s are the body
|
||||
of the function. When the function is called, it returns the result of
|
||||
the last @nonterm{expr}.
|
||||
|
||||
@defexamples[
|
||||
(code:line (define five 5) (code:comment #, @t{defines @scheme[five] to be @scheme[5]}))
|
||||
(code:line (define (piece str) (code:comment #, @t{defines @scheme[piece] as a procedure})
|
||||
(code:line (define (piece str) (code:comment #, @t{defines @scheme[piece] as a function})
|
||||
(substring str 0 five)) (code:comment #, @t{of one argument}))
|
||||
five
|
||||
(piece "hello world")
|
||||
]
|
||||
|
||||
Under the hood, a procedure definition is really the same as a
|
||||
non-procedure definition, and a procedure name does not have to be
|
||||
used in a procedure call. A procedure is just another kind of value,
|
||||
Under the hood, a function definition is really the same as a
|
||||
non-function definition, and a function name does not have to be
|
||||
used in a function call. A function is just another kind of value,
|
||||
though the printed form is necessarily less complete than the printed
|
||||
form of a number or string.
|
||||
|
||||
|
@ -93,9 +93,9 @@ piece
|
|||
substring
|
||||
]
|
||||
|
||||
A procedure definition can include multiple expressions for the
|
||||
procedure's body. In that case, only the value of the last expression
|
||||
is returned when the procedure is called. The other expressions are
|
||||
A function definition can include multiple expressions for the
|
||||
function's body. In that case, only the value of the last expression
|
||||
is returned when the function is called. The other expressions are
|
||||
evaluated only for some side-effect, such as printing.
|
||||
|
||||
@defexamples[
|
||||
|
@ -108,7 +108,7 @@ evaluated only for some side-effect, such as printing.
|
|||
Scheme programmers prefer to avoid assignment statements; it's
|
||||
important, though, to understand that multiple expressions are allowed
|
||||
in a definition body, because it explains why the following
|
||||
@scheme[nogreet] procedure simply returns its argument:
|
||||
@scheme[nogreet] function simply returns its argument:
|
||||
|
||||
@def+int[
|
||||
(define (nogreet name)
|
||||
|
@ -118,9 +118,9 @@ in a definition body, because it explains why the following
|
|||
|
||||
Withing @scheme[nogreet], there are no parentheses around
|
||||
@scheme[string-append "hello " name], so they are three separate
|
||||
expressions instead of one procedure-call expression. The expressions
|
||||
expressions instead of one function-call expression. The expressions
|
||||
@scheme[string-append] and @scheme["hello "] are evaluated, but the
|
||||
results are never used. Instead, the result of the procedure is just
|
||||
results are never used. Instead, the result of the function is just
|
||||
the result of the expression @scheme[name].
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
@ -145,7 +145,7 @@ support.
|
|||
Re-indenting not only makes the code easier to read, it gives you
|
||||
extra feedback that your parentheses are matched in the way that you
|
||||
intended. For example, if you leave out a closing parenthesis after
|
||||
the last argument to a procedure, automatic indentation starts the
|
||||
the last argument to a function, automatic indentation starts the
|
||||
next line under the first argument, instead of under the
|
||||
@scheme[define] keyword:
|
||||
|
||||
|
@ -188,20 +188,20 @@ more examples:
|
|||
]
|
||||
|
||||
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@section{Procedure Applications}
|
||||
@section{Function Calls@aux-elem{ (Procedure Applications)}}
|
||||
|
||||
We have already seen many procedure calls---or @defterm{procedure
|
||||
applications} in Scheme termonology. The syntax of a procedure
|
||||
application is
|
||||
We have already seen many function calls---or @defterm{procedure
|
||||
applications} in more traditional Scheme terminology. The syntax of a
|
||||
function call is
|
||||
|
||||
@schemeblock[
|
||||
#, app-expr-stx
|
||||
]
|
||||
|
||||
where the number of @nonterm{expr}s determines the number of
|
||||
arguments supplied to the procedure named by @nonterm{id}.
|
||||
arguments supplied to the function named by @nonterm{id}.
|
||||
|
||||
The @schememodname[big] language pre-defines many procedure
|
||||
The @schememodname[big] language pre-defines many function
|
||||
identifiers, such as @scheme[substring] and
|
||||
@scheme[string-append]. More examples are below.
|
||||
|
||||
|
@ -257,7 +257,7 @@ the third @nonterm{expr} is evaluated for the result.
|
|||
]
|
||||
|
||||
Complex conditionals can be formed by nesting @scheme[if]
|
||||
expressions. For example, you could make the @scheme[reply] procedure
|
||||
expressions. For example, you could make the @scheme[reply] function
|
||||
work when given non-strings:
|
||||
|
||||
@schemeblock[
|
||||
|
@ -269,7 +269,7 @@ work when given non-strings:
|
|||
"huh?"))
|
||||
]
|
||||
|
||||
Instead of duplicating the @scheme["huh?"] case, this procedure is
|
||||
Instead of duplicating the @scheme["huh?"] case, this function is
|
||||
better written as
|
||||
|
||||
@schemeblock[
|
||||
|
@ -336,7 +336,7 @@ 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
|
||||
Using @scheme[cond], the @scheme[reply-more] function can be more
|
||||
clearly written as follows:
|
||||
|
||||
@def+int[
|
||||
|
@ -362,11 +362,11 @@ interchangable, as long as @litchar{(} is matched with @litchar{)} and
|
|||
few key places makes Scheme code even more readable.
|
||||
|
||||
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@section{Procedure Applications, Again}
|
||||
@section{Function Calls, Again}
|
||||
|
||||
In our earlier grammar procedure applications, we oversimplified. The
|
||||
actual syntax of a procedure application allows an arbitrary
|
||||
expression for the procedure, instead of just an @nonterm{id}:
|
||||
In our earlier grammar of function calls, we oversimplified. The
|
||||
actual syntax of a function call allows an arbitrary
|
||||
expression for the function, instead of just an @nonterm{id}:
|
||||
|
||||
@schemeblock[
|
||||
#, app2-expr-stx
|
||||
|
@ -374,7 +374,7 @@ expression for the procedure, instead of just an @nonterm{id}:
|
|||
|
||||
The first @nonterm{expr} is often an @nonterm{id}, such
|
||||
as @scheme[string-append] or @scheme[+], but it can be anything that
|
||||
evaluates to an procedure. For example, it can be a conditional
|
||||
evaluates to a function. For example, it can be a conditional
|
||||
expression:
|
||||
|
||||
@def+int[
|
||||
|
@ -384,18 +384,18 @@ expression:
|
|||
(double 5)
|
||||
]
|
||||
|
||||
Syntactically, the first expression in a procedure application could
|
||||
Syntactically, the first expression in a function call could
|
||||
even be a number---but that leads to an error, since a number is not a
|
||||
procedure.
|
||||
function.
|
||||
|
||||
@interaction[(1 2 3 4)]
|
||||
|
||||
When you accidentally omit a procedure name or when you use
|
||||
When you accidentally omit a function name or when you use
|
||||
parentheses around an expression, you'll most often get an ``expected
|
||||
a procedure'' error like this one.
|
||||
|
||||
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
@section{Anonymous Procedures with @scheme[lambda]}
|
||||
@section{Anonymous Functions with @scheme[lambda]}
|
||||
|
||||
Programming in Scheme would be tedious if you had to name all of your
|
||||
numbers. Instead of writing @scheme[(+ 1 2)], you'd have to write
|
||||
|
@ -406,10 +406,10 @@ numbers. Instead of writing @scheme[(+ 1 2)], you'd have to write
|
|||
(+ a b)
|
||||
]
|
||||
|
||||
It turns out that having to name all your procedures can be tedious,
|
||||
too. For example, you might have a procedure @scheme[twice] that takes
|
||||
a procedure and an argument. Using @scheme[twice] is convenient if you
|
||||
already have a name for the procedure, such as @scheme[sqrt]:
|
||||
It turns out that having to name all your functions can be tedious,
|
||||
too. For example, you might have a function @scheme[twice] that takes
|
||||
a function and an argument. Using @scheme[twice] is convenient if you
|
||||
already have a name for the function, such as @scheme[sqrt]:
|
||||
|
||||
@def+int[
|
||||
(define (twice f v)
|
||||
|
@ -417,7 +417,7 @@ already have a name for the procedure, such as @scheme[sqrt]:
|
|||
(twice sqrt 16)
|
||||
]
|
||||
|
||||
If you want to apply a procedure that is not yet defined, you could
|
||||
If you want to call a function that is not yet defined, you could
|
||||
define it, and then pass it to @scheme[twice]:
|
||||
|
||||
@def+int[
|
||||
|
@ -429,15 +429,15 @@ define it, and then pass it to @scheme[twice]:
|
|||
But if the call to @scheme[twice] is the only place where
|
||||
@scheme[louder] is used, it's a shame to have to write a whole
|
||||
definition. In Scheme, you can use a @scheme[lambda] expression to
|
||||
produce a procedure directly. The @scheme[lambda] form is followed by
|
||||
identifiers for the procedure's arguments, and then the procedure's
|
||||
produce a function directly. The @scheme[lambda] form is followed by
|
||||
identifiers for the function's arguments, and then the function's
|
||||
body expressions:
|
||||
|
||||
@schemeblock[
|
||||
#, lambda-expr-stx
|
||||
]
|
||||
|
||||
Evaluating a @scheme[lambda] form by itself produces a procedure:
|
||||
Evaluating a @scheme[lambda] form by itself produces a function:
|
||||
|
||||
@interaction[(lambda (s) (string-append s "!"))]
|
||||
|
||||
|
@ -451,8 +451,8 @@ re-written as
|
|||
"hello")
|
||||
]
|
||||
|
||||
Another use of @scheme[lambda] is as a result for a procedure that
|
||||
generates procedures:
|
||||
Another use of @scheme[lambda] is as a result for a function that
|
||||
generates functions:
|
||||
|
||||
@def+int[
|
||||
(define (make-add-suffix s2)
|
||||
|
@ -463,9 +463,9 @@ generates procedures:
|
|||
]
|
||||
|
||||
Scheme is a @defterm{lexically scoped} language, which means that
|
||||
@scheme[s2] in the procedure returned by @scheme[make-add-suffix]
|
||||
@scheme[s2] in the function returned by @scheme[make-add-suffix]
|
||||
always refers to the argument for the call that created the
|
||||
procedure. In other words, the @scheme[lambda]-generated procedure
|
||||
function. In other words, the @scheme[lambda]-generated function
|
||||
``remembers'' the right @scheme[s2]:
|
||||
|
||||
@interaction[
|
||||
|
@ -476,10 +476,10 @@ procedure. In other words, the @scheme[lambda]-generated procedure
|
|||
]
|
||||
|
||||
We have so far referred to definitions of the form @scheme[(define #,
|
||||
@nonterm{id} #, @nonterm{expr})] as ``non-procedure
|
||||
@nonterm{id} #, @nonterm{expr})] as ``non-function
|
||||
definitions.'' This characterization is misleading, because the
|
||||
@nonterm{expr} could be a @scheme[lambda] form, in which case
|
||||
the definition is equivalent to using the ``procedure'' definition
|
||||
the definition is equivalent to using the ``function'' definition
|
||||
form. For example, the following two definitions of @scheme[louder]
|
||||
are equivalent:
|
||||
|
||||
|
@ -494,7 +494,7 @@ louder
|
|||
]
|
||||
|
||||
Note that the expression for @scheme[louder] in the second case is an
|
||||
``anonymous'' procedure written with @scheme[lambda], but, if
|
||||
``anonymous'' function written with @scheme[lambda], but, if
|
||||
possible, the compiler infers a name, anyway, to make printing and
|
||||
error reporting as informative as possible.
|
||||
|
||||
|
@ -503,7 +503,7 @@ error reporting as informative as possible.
|
|||
@scheme[define], @scheme[let], and @scheme[let*]}
|
||||
|
||||
It's time to retract another simplification in our grammar of
|
||||
Scheme. In the body of a procedure, definitions can appear before the
|
||||
Scheme. In the body of a function, definitions can appear before the
|
||||
body expressions:
|
||||
|
||||
@schemeblock[
|
||||
|
@ -511,8 +511,8 @@ body expressions:
|
|||
#, lambda2-expr-stx
|
||||
]
|
||||
|
||||
Definitions at the start of a procedure body are local to the
|
||||
procedure body.
|
||||
Definitions at the start of a function body are local to the
|
||||
function body.
|
||||
|
||||
@defexamples[
|
||||
(define (converse s)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
@title{Pairs, Lists, and Scheme Syntax}
|
||||
|
||||
The @scheme[cons] procedure actually accepts any two values, not just
|
||||
The @scheme[cons] function actually accepts any two values, not just
|
||||
a list for the second argument. When the second argument is not
|
||||
@scheme[empty] and not itself produced by @scheme[cons], the result prints
|
||||
in a special way. The two values joined with @scheme[cons] are printed
|
||||
|
@ -18,7 +18,7 @@ whitespace) in between:
|
|||
|
||||
Thus, a value produced by @scheme[cons] is not always a list. In
|
||||
general, the result of @scheme[cons] is a @defterm{pair}. The more
|
||||
traditional name for the @scheme[cons?] procedure is @scheme[pair?],
|
||||
traditional name for the @scheme[cons?] function is @scheme[pair?],
|
||||
and we'll use the traditional name from now on.
|
||||
|
||||
The name @scheme[rest] also makes less sense for non-list pairs; the
|
||||
|
@ -48,7 +48,7 @@ mistake, such as accidentally reversing the arguments to
|
|||
@interaction[(cons (list 2 3) 1) (cons 1 (list 2 3))]
|
||||
|
||||
Non-list pairs are used intentionally, sometimes. For example, the
|
||||
@scheme[make-immutable-hash-table] procedure takes a list of pairs,
|
||||
@scheme[make-immutable-hash-table] function takes a list of pairs,
|
||||
where the @scheme[car] of each pair is a key and the @scheme[cdr] is an
|
||||
arbitrary value.
|
||||
|
||||
|
@ -119,7 +119,7 @@ to be made up of the same letters.
|
|||
|
||||
Indeed, the intrinsic value of a symbol is nothing more than its
|
||||
character content. In this sense, symbols and strings are almost the
|
||||
same thing, and the main difference is how they print. The procedures
|
||||
same thing, and the main difference is how they print. The functions
|
||||
@scheme[symbol->string] and @scheme[string->symbol] convert between
|
||||
them.
|
||||
|
||||
|
|
|
@ -80,10 +80,10 @@ written with double quotes at the start and end of the string:
|
|||
@interaction["hello world"]
|
||||
|
||||
Scheme uses parentheses to wrap larger expressions---almost any kind
|
||||
of expression, other than simple constants. For example, a procedure
|
||||
call is written: open parenthesis, procedure name, argument
|
||||
of expression, other than simple constants. For example, a function
|
||||
call is written: open parenthesis, function name, argument
|
||||
expression, and closing parenthesis. The following expression calls
|
||||
the built-in procedure @scheme[substring] with the arguments
|
||||
the built-in function @scheme[substring] with the arguments
|
||||
@scheme["hello world"], @scheme[0], and @scheme[5]:
|
||||
|
||||
@interaction[(substring "hello world" 0 5)]
|
||||
|
@ -91,7 +91,7 @@ the built-in procedure @scheme[substring] with the arguments
|
|||
@; ----------------------------------------------------------------------
|
||||
@section{Definitions and Interactions}
|
||||
|
||||
You can define your own procedures that work like @scheme[subtring] by
|
||||
You can define your own functions that work like @scheme[subtring] by
|
||||
using the @scheme[define] form, like this:
|
||||
|
||||
@def+int[
|
||||
|
@ -131,7 +131,7 @@ sequence:
|
|||
(piece "howdy universe")
|
||||
]
|
||||
|
||||
The @scheme[enter!] procedure both loads the code and switches the
|
||||
The @scheme[enter!] function both loads the code and switches the
|
||||
evaluation context to the inside of the module, just like DrScheme's
|
||||
@onscreen{Run} button.
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
(module new-lambda mzscheme
|
||||
(require-for-syntax (lib "name.ss" "syntax"))
|
||||
(require-for-syntax (lib "name.ss" "syntax")
|
||||
(lib "define.ss" "syntax"))
|
||||
|
||||
(provide (all-from-except mzscheme #%datum lambda define #%app)
|
||||
(rename new-datum #%datum)
|
||||
|
@ -203,7 +204,7 @@
|
|||
(begin
|
||||
(when needs-default?
|
||||
(raise-syntax-error
|
||||
#f "default value missing" stx (syntax id)))
|
||||
#f "default-value expression missing" stx (syntax id)))
|
||||
(with-syntax ([(plain opt-ids opts kws need-kw rest) (loop #'rest #f)])
|
||||
#'((id . plain) opt-ids ([id #f #:plain] . opts) kws need-kw rest)))]
|
||||
[([id default] . rest)
|
||||
|
@ -386,7 +387,6 @@
|
|||
'kws))))]))))))]))
|
||||
|
||||
(define (missing-kw proc . args)
|
||||
(printf "~s\n" args)
|
||||
(apply
|
||||
(keyword-procedure-extract null 0 proc)
|
||||
null
|
||||
|
@ -522,17 +522,11 @@
|
|||
;; ----------------------------------------
|
||||
;; `define' with keyword arguments
|
||||
|
||||
;; Not enough syntax checking here, yet.
|
||||
;; Also, the currying notation needs to be
|
||||
;; supported.
|
||||
|
||||
(define-syntax (new-define stx)
|
||||
(syntax-case stx ()
|
||||
[(_ (id . formals) . body)
|
||||
(identifier? #'id)
|
||||
(syntax/loc stx (define id (new-lambda formals . body)))]
|
||||
[(_ . rest)
|
||||
(syntax/loc stx (define . rest))]))
|
||||
(let-values ([(id rhs)
|
||||
(normalize-definition stx #'new-lambda #t #t)])
|
||||
(quasisyntax/loc stx
|
||||
(define #,id #,rhs))))
|
||||
|
||||
;; ----------------------------------------
|
||||
;; `#%app' with keyword arguments
|
||||
|
@ -657,14 +651,18 @@
|
|||
(check-kw-args p kws)
|
||||
(values #f (car kws)))])
|
||||
(let ([args-str
|
||||
(if (null? args)
|
||||
"no arguments supplied"
|
||||
;; Hack to format arguments:
|
||||
(with-handlers ([exn:fail?
|
||||
(lambda (exn)
|
||||
(cadr (regexp-match #rx"other arguments were: (.*)$"
|
||||
(exn-message exn))))])
|
||||
(format "arguments were: ~a"
|
||||
(cadr (regexp-match
|
||||
#rx"other arguments were: (.*)$"
|
||||
(exn-message exn)))))])
|
||||
(apply raise-type-error 'x "x" 0 'x
|
||||
(append (apply append (map list kws kw-args))
|
||||
args)))])
|
||||
args))))])
|
||||
(raise
|
||||
(make-exn:fail:contract
|
||||
(if extra-kw
|
||||
|
@ -672,28 +670,28 @@
|
|||
(format
|
||||
(string-append
|
||||
"procedure application: procedure: ~e;"
|
||||
" does not expect an argument with keyword ~a; arguments were: ~a")
|
||||
" does not expect an argument with keyword ~a; ~a")
|
||||
p
|
||||
extra-kw
|
||||
args-str)
|
||||
(format
|
||||
(string-append
|
||||
"procedure application: expected a procedure that"
|
||||
" accepts keyword arguments, given ~e; arguments were: ~a")
|
||||
" accepts keyword arguments, given ~e; ~a")
|
||||
p
|
||||
args-str))
|
||||
(if missing-kw
|
||||
(format
|
||||
(string-append
|
||||
"procedure application: procedure: ~e; requires"
|
||||
" an argument with keyword ~a, not supplied; arguments were: ~a")
|
||||
" an argument with keyword ~a, not supplied; ~a")
|
||||
p
|
||||
missing-kw
|
||||
args-str)
|
||||
(format
|
||||
(string-append
|
||||
"procedure application: no case matching ~a non-keyword"
|
||||
" arguments for: ~e; arguments were: ~a")
|
||||
" arguments for: ~e; ~a")
|
||||
(- n 2)
|
||||
p
|
||||
args-str)))
|
||||
|
|
|
@ -57,17 +57,17 @@ string @scheme["art gallery"]:
|
|||
|
||||
@mr-interaction[5 "art gallery"]
|
||||
|
||||
An expression can also be a procedure call. To call a procedure, put
|
||||
an open parenthesis before the procedure name, then expressions for the
|
||||
procedure arguments, and then a close parenthesis, like this:
|
||||
An expression can also be a function call. To call a function, put
|
||||
an open parenthesis before the function name, then expressions for the
|
||||
function arguments, and then a close parenthesis, like this:
|
||||
|
||||
@mr-interaction[(circle 10)]
|
||||
|
||||
A result from the @scheme[circle] procedure is a picture value, which
|
||||
A result from the @scheme[circle] function is a picture value, which
|
||||
prints as an expression result in much the same way that numbers or
|
||||
strings print. The argument to @scheme[circle] determines the
|
||||
circle's size in pixels. As you might guess, there's a
|
||||
@scheme[rectangle] procedure that takes two arguments instead of one:
|
||||
@scheme[rectangle] function that takes two arguments instead of one:
|
||||
|
||||
@mr-interaction[(rectangle 10 20)]
|
||||
|
||||
|
@ -79,14 +79,14 @@ what happens:
|
|||
Note that DrScheme highlights the source of the error in pink.
|
||||
|
||||
In addition to basic picture constructors like @scheme[circle] and
|
||||
@scheme[rectangle], there's a @scheme[hc-append] procedure that
|
||||
combines pictures. When you start composing procedure calls in Scheme,
|
||||
@scheme[rectangle], there's a @scheme[hc-append] function that
|
||||
combines pictures. When you start composing function calls in Scheme,
|
||||
it looks like this:
|
||||
|
||||
@mr-interaction[(hc-append (circle 10) (rectangle 10 20))]
|
||||
|
||||
The hyphen in the name @scheme[hc-append] is just a part of the
|
||||
identifier; it's not @scheme[hc] minus @scheme[append]. The procedure
|
||||
identifier; it's not @scheme[hc] minus @scheme[append]. The function
|
||||
name starts with @scheme[h] because it combines pictures horizontally,
|
||||
and the next letter is @scheme[c] because the pictures are centered
|
||||
vertically. If you wonder what other functions exist (perhaps a way to
|
||||
|
@ -126,10 +126,10 @@ area. In practice, though, the definitions area is where your program
|
|||
lives---it's the file that you save---while the interaction area is
|
||||
for transient explorations and debugging tasks.
|
||||
|
||||
Let's add a procedure definition to the program. A procedure
|
||||
Let's add a function definition to the program. A function
|
||||
definition uses @scheme[define], just like our shape definitions, but with
|
||||
an open parenthesis before the procedure name, and names for the
|
||||
procedure arguments before the matching close parenthesis:
|
||||
an open parenthesis before the function name, and names for the
|
||||
function arguments before the matching close parenthesis:
|
||||
|
||||
@mr-schemeblock+eval[
|
||||
(define (square n)
|
||||
|
@ -138,7 +138,7 @@ procedure arguments before the matching close parenthesis:
|
|||
(filled-rectangle n n))
|
||||
]
|
||||
|
||||
The syntax of the definition mirrors the syntax of a procedure
|
||||
The syntax of the definition mirrors the syntax of a function
|
||||
call:
|
||||
|
||||
@mr-interaction[(square 10)]
|
||||
|
@ -156,7 +156,7 @@ definition area.
|
|||
@section{Local Binding}
|
||||
|
||||
The @scheme[define] form can be used in some places to create local
|
||||
bindings. For example, it can be used inside a procedure body:
|
||||
bindings. For example, it can be used inside a function body:
|
||||
|
||||
@mr-def+int[
|
||||
(define (four p)
|
||||
|
@ -194,21 +194,22 @@ contrast, allows later bindings to use earlier bindings:
|
|||
]
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
@section{Procedures are Values}
|
||||
@section{Functions are Values}
|
||||
|
||||
Instead of calling @scheme[circle] as a procedure, try evaluating just
|
||||
Instead of calling @scheme[circle] as a function, try evaluating just
|
||||
@scheme[circle] as an expression:
|
||||
|
||||
@mr-interaction[circle]
|
||||
|
||||
That is, the identifier @scheme[circle] is bound to a procedure, just
|
||||
like @scheme[c] is bound to a circle. Unlike a cicrle picture, there's
|
||||
not a simple way of completely printing the procedure, so DrScheme just
|
||||
prints @procedure{circle}.
|
||||
That is, the identifier @scheme[circle] is bound to a function
|
||||
(a.k.a. ``procedure''), just like @scheme[c] is bound to a
|
||||
circle. Unlike a cicrle picture, there's not a simple way of
|
||||
completely printing the function, so DrScheme just prints
|
||||
@procedure{circle}.
|
||||
|
||||
This example shows that procedures are values, just like numbers and
|
||||
pictures (even if they don't print as nicely). Since procedures are
|
||||
values, you can define procedures that expect other procedures as
|
||||
This example shows that functions are values, just like numbers and
|
||||
pictures (even if they don't print as nicely). Since functions are
|
||||
values, you can define functions that expect other functions as
|
||||
arguments:
|
||||
|
||||
@mr-def+int[
|
||||
|
@ -218,21 +219,21 @@ arguments:
|
|||
(series square)
|
||||
]
|
||||
|
||||
When calling a procedure that accepts a procedure argument, the
|
||||
argument procedure often isn't needed anywhere else. Having to write
|
||||
When calling a function that accepts a function argument, the
|
||||
argument function often isn't needed anywhere else. Having to write
|
||||
down the function via @scheme[define] would be a hassle, because you
|
||||
have to make up a name and find a place to put the procedure
|
||||
have to make up a name and find a place to put the function
|
||||
definition. The alternative is to use @scheme[lambda], which creates an
|
||||
anonymous procedure:
|
||||
anonymous function:
|
||||
|
||||
@mr-interaction[(series (lambda (size) (checkerboard (square size))))]
|
||||
|
||||
The parenthesized names after a @scheme[lambda] are the arguments to
|
||||
the procedure, and the expression after the argument names is the
|
||||
procedure body. Using the word ``lambda'' instead of ``function'' or
|
||||
the function, and the expression after the argument names is the
|
||||
function body. Using the word ``lambda'' instead of ``function'' or
|
||||
``procedure'' is part of Scheme's history and culture.
|
||||
|
||||
A procedure-form @scheme[define] is really a shorthand for a simple
|
||||
A function @scheme[define] is really a shorthand for a simple
|
||||
@scheme[define] using @scheme[lambda] as the value. For example, the
|
||||
@scheme[series] definition could be written as
|
||||
|
||||
|
@ -242,7 +243,7 @@ A procedure-form @scheme[define] is really a shorthand for a simple
|
|||
(hc-append 4 (mk 5) (mk 10) (mk 20))))
|
||||
]
|
||||
|
||||
Most Schemers prefer to use the shorthand procedure form with
|
||||
Most Schemers prefer to use the shorthand function form with
|
||||
@scheme[define] instead of expanding to @scheme[lambda].
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
@ -254,7 +255,7 @@ environment of the expression determines the identifier's
|
|||
binding. This rule applies to identifiers in a @scheme[lambda] body as
|
||||
well as anywhere else.
|
||||
|
||||
For example, in the following @scheme[color-series] procedure the uses
|
||||
For example, in the following @scheme[color-series] function the uses
|
||||
of @scheme[mk] in each @scheme[lambda] form to refer to the argument of
|
||||
@scheme[color-series], since that's the binding that is textually in
|
||||
scope:
|
||||
|
@ -269,8 +270,8 @@ scope:
|
|||
(rgb-series square)
|
||||
]
|
||||
|
||||
Here's another example, where @scheme[rgb-maker] takes a procedure and
|
||||
returns a new one that remembers and uses the original procedure.
|
||||
Here's another example, where @scheme[rgb-maker] takes a function and
|
||||
returns a new one that remembers and uses the original function.
|
||||
|
||||
@mr-def+int[
|
||||
(define (rgb-maker mk)
|
||||
|
@ -282,7 +283,7 @@ returns a new one that remembers and uses the original procedure.
|
|||
(series (rgb-maker square))
|
||||
]
|
||||
|
||||
Note how composing procedures via @scheme[rgb-maker] creates a
|
||||
Note how composing functions via @scheme[rgb-maker] creates a
|
||||
different alignment of objects within the picture compared to using
|
||||
@scheme[rgb-series].
|
||||
|
||||
|
@ -293,7 +294,7 @@ Scheme inherits much of its style from the langauge Lisp, whose name
|
|||
originally stood for ``LISt Processor,'' and lists remain an important
|
||||
part of Scheme.
|
||||
|
||||
The @scheme[list] procedure takes any number of arguments and returns
|
||||
The @scheme[list] function takes any number of arguments and returns
|
||||
a list containing the given values:
|
||||
|
||||
@mr-interaction[(list "red" "green" "blue")
|
||||
|
@ -310,9 +311,9 @@ documentation and in DrScheme, result parentheses are printed in blue,
|
|||
unlike expression parentheses.
|
||||
|
||||
If you have a list, then you'll eventually want to do something with
|
||||
each of the elements. The @scheme[map] procedure takes a list and a
|
||||
procedure to apply to each element of the list; it returns a new list
|
||||
to combine the procedure's results:
|
||||
each of the elements. The @scheme[map] function takes a list and a
|
||||
function to apply to each element of the list; it returns a new list
|
||||
to combine the function's results:
|
||||
|
||||
@mr-def+int[
|
||||
(define (rainbow p)
|
||||
|
@ -322,8 +323,8 @@ to combine the procedure's results:
|
|||
(rainbow (square 5))
|
||||
]
|
||||
|
||||
Another procedure that works with lists is @scheme[apply]. Like
|
||||
@scheme[map], it takes a procedure and a list, but a procedure given
|
||||
Another function that works with lists is @scheme[apply]. Like
|
||||
@scheme[map], it takes a function and a list, but a function given
|
||||
to @scheme[apply] should take all of the arguments at once, instead of
|
||||
each one individually. The @scheme[apply] function is especially
|
||||
useful with functions that take any number of arguments, such as
|
||||
|
@ -336,8 +337,8 @@ useful with functions that take any number of arguments, such as
|
|||
Note that @scheme[(vc-append (rainbow (square 5)))] would not work,
|
||||
because @scheme[vc-append] does not want a list as an argument; it
|
||||
wants a picture as an argument, and it is willing to accept any number
|
||||
of them. The @scheme[apply] procedure bridges the gap between a
|
||||
procedure that wants many arguments and a list of those arguments as a
|
||||
of them. The @scheme[apply] function bridges the gap between a
|
||||
function that wants many arguments and a list of those arguments as a
|
||||
single value.
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
@ -350,12 +351,12 @@ Since your program in the definitions window starts with
|
|||
all of the code that you put in the definitions window is inside a
|
||||
module. Furthermore, the module intially imports everything from the
|
||||
module designated by @schememodname[slideshow], which exports
|
||||
picture-making procedures as well as more commonly used procedures
|
||||
picture-making functions as well as more commonly used functions
|
||||
such as @scheme[list] and @scheme[map].
|
||||
|
||||
To import additional libraries, use the @scheme[require] form. For
|
||||
example, the library @scheme[(lib "flash.ss" "texpict")] provides a
|
||||
@scheme[filled-flash] procedure:
|
||||
@scheme[filled-flash] function:
|
||||
|
||||
@mr-def+int[
|
||||
(require (lib "flash.ss" "texpict"))
|
||||
|
@ -408,8 +409,8 @@ Modules are named and distributed in various ways:
|
|||
and when you run this later program, a rainbow list of squares
|
||||
is the output. Note that @file{use.ss} is written using the
|
||||
initial import @schememodname[little], which does not
|
||||
supply any picture-making procedures itself---but does provide
|
||||
@scheme[require] and the procedure-calling syntax.}
|
||||
supply any picture-making functions itself---but does provide
|
||||
@scheme[require] and the function-calling syntax.}
|
||||
|
||||
]
|
||||
|
||||
|
@ -433,15 +434,15 @@ Here's another library to try:
|
|||
|
||||
Instead of a circle, the result is a picture of the code that, if it
|
||||
were used as an expression, would produce a circle. In other words,
|
||||
@scheme[code] is not a procedure, but instead a new syntactic form for
|
||||
@scheme[code] is not a function, but instead a new syntactic form for
|
||||
creating pictures; the bit between the opening parenthesese with
|
||||
@scheme[code] is not an expression, but instead manipulated by the
|
||||
@scheme[code] syntactic form.
|
||||
|
||||
This helps explain what we meant in the previous section when we said
|
||||
that @schememodname[little] provides @scheme[require] and the
|
||||
procedure-calling syntax. Libraries are not restricted to exporting
|
||||
values, such as procedures; they can also define new syntax. In this
|
||||
function-calling syntax. Libraries are not restricted to exporting
|
||||
values, such as functions; they can also define new syntax. In this
|
||||
sense, Scheme isn't exactly language at all; it's more of an idea for
|
||||
how to structure a language so that you can extend it or create
|
||||
entirely new languages.
|
||||
|
@ -487,7 +488,7 @@ take you a long way!
|
|||
|
||||
An object system is another example of a sophisticated language
|
||||
extension that is worth learning and using for a Scheme users. Objects
|
||||
are sometimes better than procedures, even when you have
|
||||
are sometimes better than functions, even when you have
|
||||
@scheme[lambda], and objects work especially well for graphical user
|
||||
interfaces. The API for Scheme's GUI and graphics system is expressed
|
||||
in terms of objects and classes.
|
||||
|
@ -518,8 +519,8 @@ argument @scheme[#t] in this case is the boolean constant ``true.''
|
|||
Pictures generated with @schememodname[slideshow] encapsulate a
|
||||
function that uses MrEd's drawing commands to render the picture to a
|
||||
drawing context, such as a canvas in a frame. The
|
||||
@scheme[make-pict-drawer] procedure from @schememodname[slideshow]
|
||||
exposes a picture's drawing procedure. We can use
|
||||
@scheme[make-pict-drawer] function from @schememodname[slideshow]
|
||||
exposes a picture's drawing function. We can use
|
||||
@scheme[make-pict-drawer] in a canvas-painting callback to draw a
|
||||
picture into a canvas:
|
||||
|
||||
|
@ -550,7 +551,7 @@ is really just a @scheme[lambda] in disguise. While those are all part
|
|||
of PLT Scheme, they are not the main ingredients of day-to-day programming
|
||||
in PLT Scheme.
|
||||
|
||||
Instead, PLT Scheme programmers typically program with procedures,
|
||||
Instead, PLT Scheme programmers typically program with functions,
|
||||
records, objects, exceptions, regular expressions, modules, and
|
||||
threads. That is, instead of a ``minimalist'' language---which is the
|
||||
way that Scheme is often described---PLT Scheme offers a rich language
|
||||
|
|
|
@ -394,3 +394,6 @@ and in the @scheme[body]s.
|
|||
@;------------------------------------------------------------------------
|
||||
@section{Sequencing: @scheme[begin]}
|
||||
|
||||
@;------------------------------------------------------------------------
|
||||
@section[#:tag "mz:define"]{Definitions: @scheme[define] and @scheme[define-values]}
|
||||
|
||||
|
|
|
@ -93,6 +93,9 @@ have Scribble's @file{scheme.ss} and @file{manual.ss}).
|
|||
@scheme[decode-content], and wraps the result as an element with
|
||||
style @scheme[#f].}
|
||||
|
||||
@def-elem-proc[aux-elem]{Like @scheme[elem], but creates an
|
||||
@scheme[aux-element].}
|
||||
|
||||
@def-style-proc[italic]
|
||||
@def-style-proc[bold]
|
||||
@def-style-proc[tt]
|
||||
|
|
|
@ -293,10 +293,11 @@ as a file name (e.g., in typewriter font and in in quotes).}
|
|||
as a command line (e.g., in typewriter font).}
|
||||
|
||||
@; ------------------------------------------------------------------------
|
||||
@section{Section Links}
|
||||
@section[#:tag "scribble:manual:section-links"]{Section Links}
|
||||
|
||||
@defproc[(secref [tag string?]) element?]{Inserts the hyperlinked
|
||||
title of the section tagged @scheme[tag].}
|
||||
title of the section tagged @scheme[tag], but @scheme{aux-element}
|
||||
items in the title content are omitted in the hyperlink label.}
|
||||
|
||||
@defproc[(seclink [tag string?] [pre-content any/c] ...) element?]{The content from
|
||||
@scheme[pre-content] is hyperlinked to the section tagged @scheme[tag].}
|
||||
|
@ -305,7 +306,6 @@ title of the section tagged @scheme[tag].}
|
|||
@scheme[pre-content] is hyperlinked to the definition of @scheme[id].}
|
||||
|
||||
|
||||
|
||||
@; ------------------------------------------------------------------------
|
||||
@section{Indexing}
|
||||
|
||||
|
|
|
@ -194,6 +194,14 @@ section, and the last argument correspond to global information
|
|||
|
||||
}
|
||||
|
||||
@defstruct[(aux-element element) ()]{
|
||||
|
||||
Instances of this structure type are intended for use in titles, where
|
||||
the auxiliary part of the title can be omitted in hyperlinks. See, for
|
||||
example, @scheme[secref].
|
||||
|
||||
}
|
||||
|
||||
@defstruct[delayed-element ([render (any/c part? any/c . -> . list?)])]{
|
||||
|
||||
The @scheme[render] procedure's arguments are the same as for
|
||||
|
|
|
@ -4,11 +4,9 @@
|
|||
|
||||
(provide normalize-definition)
|
||||
|
||||
;; This code was shamefully copied from MzScheme's startup.ss!
|
||||
|
||||
(define normalize-definition
|
||||
(case-lambda
|
||||
[(stx lambda-stx check-context?)
|
||||
[(stx lambda-stx check-context? allow-key+opt?)
|
||||
(when (and check-context?
|
||||
(memq (syntax-local-context) '(expression)))
|
||||
(raise-syntax-error
|
||||
|
@ -45,19 +43,75 @@
|
|||
;; a proc maker instead of a final proc to enable
|
||||
;; left-to-right checking of the function protos
|
||||
(lambda (proto)
|
||||
(let-values ([(args mk-rhs)
|
||||
(let-values ([(args rests mk-rhs)
|
||||
(syntax-case proto ()
|
||||
[(id arg ...)
|
||||
(values (syntax->list #'(arg ...))
|
||||
null
|
||||
(lambda (body)
|
||||
(quasisyntax/loc stx (#,lambda-stx (arg ...)
|
||||
. #,body))))]
|
||||
[(id arg ... . rest)
|
||||
(values (syntax->list #'(arg ... rest))
|
||||
(values (syntax->list #'(arg ...))
|
||||
(list #'rest)
|
||||
(lambda (body)
|
||||
(quasisyntax/loc stx
|
||||
(#,lambda-stx (arg ... . rest)
|
||||
. #,body))))])])
|
||||
(let* ([args (if allow-key+opt?
|
||||
(let* ([kw-ht (make-hash-table)]
|
||||
[check-kw
|
||||
(lambda (kw)
|
||||
(when (hash-table-get kw-ht (syntax-e kw) #f)
|
||||
(raise-syntax-error
|
||||
#f
|
||||
"duplicate keyword for argument"
|
||||
stx
|
||||
kw))
|
||||
(hash-table-put! kw-ht (syntax-e kw) #t))])
|
||||
(let loop ([args args][need-def? #f])
|
||||
(syntax-case args ()
|
||||
[() null]
|
||||
[(id . more)
|
||||
(identifier? #'id)
|
||||
(if need-def?
|
||||
(raise-syntax-error
|
||||
#f
|
||||
"default-value expression missing"
|
||||
stx
|
||||
#'id)
|
||||
(cons #'id (loop #'more #f)))]
|
||||
[([id def-expr] . more)
|
||||
(identifier? #'id)
|
||||
(cons #'id (loop #'more #t))]
|
||||
[(kw id . more)
|
||||
(and (keyword? (syntax-e #'kw))
|
||||
(identifier? #'id))
|
||||
(begin
|
||||
(check-kw #'kw)
|
||||
(cons #'id (loop #'more #t)))]
|
||||
[(kw [id def-expr] . more)
|
||||
(and (keyword? (syntax-e #'kw))
|
||||
(identifier? #'id))
|
||||
(begin
|
||||
(check-kw #'kw)
|
||||
(cons #'id (loop #'more #t)))]
|
||||
[(kw . more)
|
||||
(keyword? (syntax-e #'kw))
|
||||
(raise-syntax-error #f
|
||||
"missing argument identifier after keyword"
|
||||
stx
|
||||
#'kw)]
|
||||
[(x . more)
|
||||
(raise-syntax-error
|
||||
#f
|
||||
"not an identifier, identifier with default, or keyword for procedure argument"
|
||||
stx
|
||||
#'x)])))
|
||||
args)]
|
||||
[all-args (if (null? rests)
|
||||
args
|
||||
(append args rests))])
|
||||
(for-each (lambda (a)
|
||||
(unless (identifier? a)
|
||||
(raise-syntax-error
|
||||
|
@ -65,15 +119,15 @@
|
|||
"not an identifier for procedure argument"
|
||||
stx
|
||||
a)))
|
||||
args)
|
||||
(let ([dup (check-duplicate-identifier args)])
|
||||
all-args)
|
||||
(let ([dup (check-duplicate-identifier all-args)])
|
||||
(when dup
|
||||
(raise-syntax-error
|
||||
#f
|
||||
"duplicate argument identifier"
|
||||
stx
|
||||
dup)))
|
||||
mk-rhs))]
|
||||
mk-rhs)))]
|
||||
[general-proto
|
||||
;; proto is guaranteed to be a stx-pair
|
||||
(lambda (proto)
|
||||
|
@ -106,4 +160,5 @@
|
|||
"bad syntax (no expressions for procedure body)"
|
||||
stx))
|
||||
(values id (mk-rhs #'body)))])]
|
||||
[(stx lambda-stx) (normalize-definition stx lambda-stx #t)])))
|
||||
[(stx lambda-stx check-context?) (normalize-definition stx lambda-stx check-context? #f)]
|
||||
[(stx lambda-stx) (normalize-definition stx lambda-stx #t #f)])))
|
||||
|
|
|
@ -114,9 +114,9 @@ _toplevel.ss_: helper for moduleless compilation and expansion
|
|||
_define.ss_: handling all the same function forms as `define'
|
||||
======================================================================
|
||||
|
||||
> (normalize-definition defn-stx lambda-id-stx [check-context?]) -
|
||||
> (normalize-definition defn-stx lambda-id-stx [check-context? opt+kws?]) -
|
||||
takes a definition form whose shape is like `define' (though
|
||||
possibly with a different keyword) and returns two values: the
|
||||
possibly with a different name) and returns two values: the
|
||||
defined identifier and the right-hand side expression.
|
||||
|
||||
To generate the right-hand side, this function may need to insert
|
||||
|
@ -128,6 +128,10 @@ _define.ss_: handling all the same function forms as `define'
|
|||
`(syntax-local-context)' indicates that the current context is an
|
||||
expression context. The default value of `check-context?' is #t.
|
||||
|
||||
If `opt-kws?' is #t, then arguments of the form `[id expr]',
|
||||
`keyword id', and `keyword [id expr]' are allowed, and they are
|
||||
preserved in the expansion.
|
||||
|
||||
======================================================================
|
||||
_struct.ss_: generating the same names as `define-struct'
|
||||
======================================================================
|
||||
|
|
Loading…
Reference in New Issue
Block a user