doc work, and also generalize normalize-definition to work with opts and kws

svn: r6665
This commit is contained in:
Matthew Flatt 2007-06-15 01:59:06 +00:00
parent ea5b3493f3
commit 2e536dc70e
26 changed files with 520 additions and 294 deletions

View File

@ -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)]

View File

@ -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)))

View File

@ -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"))

View File

@ -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,22 +133,35 @@
(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)
(cond
[(element? c) (content->string (element-content c))]
[(string? c) c]
[else (case c
[(ndash) "--"]
[(ldquo rdquo) "\""]
[(rsquo) "'"]
[(rarr) "->"]
[else (format "~s" 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]
[else (case c
[(ndash) "--"]
[(ldquo rdquo) "\""]
[(rsquo) "'"]
[(rarr) "->"]
[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)])]))
)

View File

@ -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

View File

@ -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

View File

@ -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"]

View File

@ -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.

View File

@ -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}

View File

@ -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.

View File

@ -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"].}
}

View File

@ -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)}}
@; ----------------------------------------------------------------------

View File

@ -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.

View File

@ -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:

View File

@ -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)

View File

@ -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)

View File

@ -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.

View File

@ -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.

View File

@ -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
;; Hack to format arguments:
(with-handlers ([exn:fail?
(lambda (exn)
(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)))])
(if (null? args)
"no arguments supplied"
;; Hack to format arguments:
(with-handlers ([exn:fail?
(lambda (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))))])
(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)))

View File

@ -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

View File

@ -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]}

View File

@ -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]

View File

@ -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}

View File

@ -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

View File

@ -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,35 +43,91 @@
;; 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))))])])
(for-each (lambda (a)
(unless (identifier? a)
(raise-syntax-error
#f
"not an identifier for procedure argument"
stx
a)))
args)
(let ([dup (check-duplicate-identifier args)])
(when dup
(raise-syntax-error
#f
"duplicate argument identifier"
stx
dup)))
mk-rhs))]
(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
#f
"not an identifier for procedure argument"
stx
a)))
all-args)
(let ([dup (check-duplicate-identifier all-args)])
(when dup
(raise-syntax-error
#f
"duplicate argument identifier"
stx
dup)))
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)])))

View File

@ -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'
======================================================================