partly rackety guide

This commit is contained in:
Matthew Flatt 2010-04-27 14:09:44 -06:00
parent 4537240f1f
commit 1fedf04739
46 changed files with 1697 additions and 1598 deletions

View File

@ -611,43 +611,64 @@
((loop init-line! (if qq? quote-depth +inf.0) qq?) (unbox (syntax-e c))))]
[(hash? (syntax-e c))
(advance c init-line!)
(let ([equal-table? (not (hash-eq? (syntax-e c)))]
(let ([equal-table? (hash-equal? (syntax-e c))]
[eqv-table? (hash-eq? (syntax-e c))]
[quote-depth (to-quoted "`" qq? quote-depth out color? inc-src-col)])
(out (if equal-table?
"#hash"
"#hasheq")
(if eqv-table?
"#hasheqv"
"#hasheq"))
value-color)
(let ([delta (+ 5 (if equal-table? 2 0))]
(let ([delta (+ 5 (if equal-table? 0 (if eqv-table? 3 2)))]
[orig-col src-col])
(set! src-col (+ src-col delta))
(hash-set! next-col-map src-col dest-col)
((loop init-line! (if qq? quote-depth +inf.0) qq?)
(let* ([l (sort (hash-map (syntax-e c) cons)
(lambda (a b)
(< (or (syntax-position (cdr a)) -inf.0)
(or (syntax-position (cdr b)) -inf.0))))]
[l2 (for/list ([p (in-list l)])
(let* ([tentative (syntax-ize (car p) 0)]
[width (syntax-span tentative)])
(datum->syntax
#f
(make-forced-pair
(syntax-ize (car p)
(max 0 (- (syntax-column (cdr p))
width
3))
(syntax-line (cdr p)))
(cdr p))
(vector 'here
(syntax-line (cdr p))
(max 0 (- (syntax-column (cdr p)) width 4))
(max 1 (- (syntax-position (cdr p)) width 4))
(+ (syntax-span (cdr p)) width 5)))))])
(datum->syntax #f l2 (vector (syntax-source c)
(syntax-line c)
(+ (syntax-column c) delta)
(+ (syntax-position c) delta)
(max 1 (- (syntax-span c) delta))))))
(let*-values ([(l) (sort (hash-map (syntax-e c) cons)
(lambda (a b)
(< (or (syntax-position (cdr a)) -inf.0)
(or (syntax-position (cdr b)) -inf.0))))]
[(col0) (+ (syntax-column c) delta 2)]
[(l2 pos line) (for/fold ([l2 null][col col0][line (syntax-line c)])
([p (in-list l)])
(let* ([tentative (syntax-ize (car p) 0)]
[width (syntax-span tentative)]
[col (if (= line (syntax-line (cdr p)))
col
col0)])
(let ([key
(let ([e (syntax-ize (car p)
(max 0 (- (syntax-column (cdr p))
width
3))
(syntax-line (cdr p)))])
(if ((syntax-column e) . <= . col)
e
(datum->syntax #f
(syntax-e e)
(vector (syntax-source e)
(syntax-line e)
col
(syntax-position e)
(+ (syntax-span e) (- (syntax-column e) col))))))])
(let ([elem
(datum->syntax
#f
(make-forced-pair key (cdr p))
(vector 'here
(syntax-line (cdr p))
(max 0 (- (syntax-column key) 1))
(max 1 (- (syntax-position key) 1))
(+ (syntax-span (cdr p)) (syntax-span key) 5)))])
(values (cons elem l2)
(+ (syntax-column elem) (syntax-span elem) 2)
(syntax-line elem))))))])
(datum->syntax #f (reverse l2) (vector (syntax-source c)
(syntax-line c)
(+ (syntax-column c) delta)
(+ (syntax-position c) delta)
(max 1 (- (syntax-span c) delta))))))
(set! src-col (+ orig-col (syntax-span c)))))]
[(graph-reference? (syntax-e c))
(advance c init-line!)

View File

@ -12,16 +12,16 @@ An expression of the form
]
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]).
application}---when @racket[_proc-expr] is not an identifier that is
bound as a syntax transformer (such as @racket[if] or
@racket[define]).
@section{Evaluation Order and Arity}
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] produces a function that accepts
as many arguments as supplied @scheme[_arg-expr]s, the function is
@racket[_proc-expr] and all @racket[_arg-expr]s in order (left to
right). Then, if @racket[_proc-expr] produces a function that accepts
as many arguments as supplied @racket[_arg-expr]s, the function is
called. Otherwise, an exception is raised.
@examples[
@ -31,10 +31,10 @@ called. Otherwise, an exception is raised.
(1 2 3)
]
Some functions, such as @scheme[cons], accept a fixed number of
arguments. Some functions, such as @scheme[+] or @scheme[list], accept
Some functions, such as @racket[cons], accept a fixed number of
arguments. Some functions, such as @racket[+] or @racket[list], accept
any number of arguments. Some functions accept a range of argument
counts; for example @scheme[substring] accepts either two or three
counts; for example @racket[substring] accepts either two or three
arguments. A function's @idefterm{arity} is the number of arguments
that it accepts.
@ -42,9 +42,9 @@ that it accepts.
@section[#:tag "keyword-args"]{Keyword Arguments}
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]:
by-position arguments. For that case, an @racket[_arg] can be an
@racket[_arg-keyword _arg-expr] sequence instead of just a
@racket[_arg-expr]:
@guideother{@secref["keywords"] introduces keywords.}
@ -56,37 +56,37 @@ by-position arguments. For that case, an @scheme[_arg] can be an
For example,
@schemeblock[(go "super.ss" #:mode 'fast)]
@racketblock[(go "super.ss" #:mode 'fast)]
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
calls the function bound to @racket[go] with @racket["super.ss"] as a
by-position argument, and with @racket['fast] as an argument
associated with the @racket[#:mode] keyword. A keyword is implicitly
paired with the expression that follows it.
Since a keyword by itself is not an expression, then
@schemeblock[(go "super.ss" #:mode #:fast)]
@racketblock[(go "super.ss" #:mode #:fast)]
is a syntax error. The @scheme[#:mode] keyword must be followed by an
expression to produce an argument value, and @scheme[#:fast] is not an
is a syntax error. The @racket[#:mode] keyword must be followed by an
expression to produce an argument value, and @racket[#: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 function accepts keyword
The order of keyword @racket[_arg]s determines the order in which
@racket[_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
above call to @racket[go] can be equivalently written
@schemeblock[(go #:mode 'fast "super.ss")]
@racketblock[(go #:mode 'fast "super.ss")]
@refdetails["application"]{procedure applications}
@;------------------------------------------------------------------------
@section[#:tag "apply"]{The @scheme[apply] Function}
@section[#:tag "apply"]{The @racket[apply] Function}
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:
apply a function like @racket[+] to all of the items in the list:
@def+int[
(define (avg lst) (code:comment @#,elem{doesn't work...})
@ -102,7 +102,7 @@ apply a function like @scheme[+] to all of the items in the list:
(avg '(1 2))
]
The @scheme[apply] function offers a way around this restriction. It
The @racket[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:
@ -114,9 +114,9 @@ function to the arguments:
(avg '(1 2 3 4))
]
As a convenience, the @scheme[apply] function accepts additional
As a convenience, the @racket[apply] function accepts additional
arguments between the function and the list. The additional arguments
are effectively @scheme[cons]ed onto the argument list:
are effectively @racket[cons]ed onto the argument list:
@def+int[
(define (anti-sum lst)
@ -124,15 +124,15 @@ are effectively @scheme[cons]ed onto the argument list:
(anti-sum '(1 2 3))
]
The @scheme[apply] function supports only by-position arguments. To
The @racket[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
@racket[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 keywords (sorted by @racket[keyword<]), and the second
list contains a corresponding argument for each keyword. The third
list contains by-position function arguments, as for @scheme[apply].
list contains by-position function arguments, as for @racket[apply].
@schemeblock[
@racketblock[
(keyword-apply go
'(#:mode)
'(fast)

View File

@ -5,25 +5,25 @@
@title[#:tag "begin"]{Sequencing}
Scheme programmers prefer to write programs with as few side-effects
Racket programmers prefer to write programs with as few side-effects
as possible, since purely functional code is more easily tested and
composed into larger programs. Interaction with the external
environment, however, requires sequencing, such as when writing to a
display, opening a graphical window, or manipulating a file on disk.
@;------------------------------------------------------------------------
@section{Effects Before: @scheme[begin]}
@section{Effects Before: @racket[begin]}
@refalso["begin"]{@scheme[begin]}
@refalso["begin"]{@racket[begin]}
A @scheme[begin] expression sequences expressions:
A @racket[begin] expression sequences expressions:
@specform[(begin expr ...+)]{}
The @scheme[_expr]s are evaluated in order, and the result of all but
the last @scheme[_expr] is ignored. The result from the last
@scheme[_expr] is the result of the @scheme[begin] form, and it is in
tail position with respect to the @scheme[begin] form.
The @racket[_expr]s are evaluated in order, and the result of all but
the last @racket[_expr] is ignored. The result from the last
@racket[_expr] is the result of the @racket[begin] form, and it is in
tail position with respect to the @racket[begin] form.
@defexamples[
(define (print-triangle height)
@ -36,8 +36,8 @@ tail position with respect to the @scheme[begin] form.
(print-triangle 4)
]
Many forms, such as @scheme[lambda] or @scheme[cond] support a
sequence of expressions even without a @scheme[begin]. Such positions are
Many forms, such as @racket[lambda] or @racket[cond] support a
sequence of expressions even without a @racket[begin]. Such positions are
sometimes said to have an @defterm{implicit begin}.
@defexamples[
@ -50,10 +50,10 @@ sometimes said to have an @defterm{implicit begin}.
(print-triangle 4)
]
The @scheme[begin] form is special at the top level, at module level,
or as a @scheme[body] after only internal definitions. In those
The @racket[begin] form is special at the top level, at module level,
or as a @racket[body] after only internal definitions. In those
positions, instead of forming an expression, the content of
@scheme[begin] is spliced into the surrounding context.
@racket[begin] is spliced into the surrounding context.
@defexamples[
(let ([curly 0])
@ -67,18 +67,18 @@ This splicing behavior is mainly useful for macros, as we discuss
later in @secref["macros"].
@;------------------------------------------------------------------------
@section{Effects After: @scheme[begin0]}
@section{Effects After: @racket[begin0]}
@refalso["begin"]{@scheme[begin0]}
@refalso["begin"]{@racket[begin0]}
A @scheme[begin0] expression has the same syntax as a @scheme[begin]
A @racket[begin0] expression has the same syntax as a @racket[begin]
expression:
@specform[(begin0 expr ...+)]{}
The difference is that @scheme[begin0] returns the result of the first
@scheme[expr], instead of the result of the last @scheme[expr]. The
@scheme[begin0] form is useful for implementing side-effects that
The difference is that @racket[begin0] returns the result of the first
@racket[expr], instead of the result of the last @racket[expr]. The
@racket[begin0] form is useful for implementing side-effects that
happen after a computation, especially in the case where the
computation produces an unknown number of results.
@ -93,26 +93,26 @@ computation produces an unknown number of results.
]
@;------------------------------------------------------------------------
@section[#:tag "when+unless"]{Effects If...: @scheme[when] and @scheme[unless]}
@section[#:tag "when+unless"]{Effects If...: @racket[when] and @racket[unless]}
@refalso["when+unless"]{@scheme[when] and @scheme[unless]}
@refalso["when+unless"]{@racket[when] and @racket[unless]}
The @scheme[when] form combines an @scheme[if]-style conditional with
The @racket[when] form combines an @racket[if]-style conditional with
sequencing for the ``then'' clause and no ``else'' clause:
@specform[(when test-expr then-expr ...)]
If @scheme[_test-expr] produces a true value, then all of the
@scheme[_then-expr]s are evaluated. Otherwise, no @scheme[_then-expr]s
If @racket[_test-expr] produces a true value, then all of the
@racket[_then-expr]s are evaluated. Otherwise, no @racket[_then-expr]s
are evaluated. The result is @|void-const| in any case.
The @scheme[unless] form is similar:
The @racket[unless] form is similar:
@specform[(unless test-expr then-expr ...)]
The difference is that the @scheme[_test-expr] result is inverted: the
@scheme[_then-expr]s are evaluated only if the @scheme[_test-expr]
result is @scheme[#f].
The difference is that the @racket[_test-expr] result is inverted: the
@racket[_then-expr]s are evaluated only if the @racket[_test-expr]
result is @racket[#f].
@defexamples[
(define (enumerate lst)

View File

@ -7,19 +7,19 @@
The context of an expression determines the meaning of identifiers
that appear in the expression. In particular, starting a module with
the language @schememodname[scheme], as in
the language @racketmodname[racket], as in
@schememod[scheme]
@racketmod[racket]
means that, within the module, the identifiers described in this guide
start with the meaning described here: @scheme[cons] refers to the
function that creates a pair, @scheme[car] refers to the function
start with the meaning described here: @racket[cons] refers to the
function that creates a pair, @racket[car] refers to the function
that extracts the first element of a pair, and so on.
@guideother{@secref["symbols"] introduces the syntax of
identifiers.}
Forms like @scheme[define], @scheme[lambda], and @scheme[let]
Forms like @racket[define], @racket[lambda], and @racket[let]
associate a meaning with one or more identifiers; that is, they
@defterm{bind} identifiers. The part of the program for which the
binding applies is the @defterm{scope} of the binding. The set of
@ -28,8 +28,8 @@ bindings in effect for a given expression is the expression's
For example, in
@schememod[
scheme
@racketmod[
racket
(define f
(lambda (x)
@ -39,19 +39,19 @@ scheme
(f 10)
]
the @scheme[define] is a binding of @scheme[f], the @scheme[lambda]
has a binding for @scheme[x], and the @scheme[let] has a binding for
@scheme[y]. The scope of the binding for @scheme[f] is the entire
module; the scope of the @scheme[x] binding is @scheme[(let ([y 5]) (+
x y))]; and the scope of the @scheme[y] binding is just @scheme[(+ x
y)]. The environment of @scheme[(+ x y)] includes bindings for
@scheme[y], @scheme[x], and @scheme[f], as well as everything in
@schememodname[scheme].
the @racket[define] is a binding of @racket[f], the @racket[lambda]
has a binding for @racket[x], and the @racket[let] has a binding for
@racket[y]. The scope of the binding for @racket[f] is the entire
module; the scope of the @racket[x] binding is @racket[(let ([y 5]) (+
x y))]; and the scope of the @racket[y] binding is just @racket[(+ x
y)]. The environment of @racket[(+ x y)] includes bindings for
@racket[y], @racket[x], and @racket[f], as well as everything in
@racketmodname[racket].
A module-level @scheme[define] can bind only identifiers that are not
already bound within the module. For example, @scheme[(define cons 1)]
is a syntax error in a @schememodname[scheme] module, since @scheme[cons]
is provided by @schememodname[scheme]. A local @scheme[define] or other
A module-level @racket[define] can bind only identifiers that are not
already bound within the module. For example, @racket[(define cons 1)]
is a syntax error in a @racketmodname[racket] module, since @racket[cons]
is provided by @racketmodname[racket]. A local @racket[define] or other
binding forms, however, can give a new local binding for an identifier
that already has a binding; such a binding @defterm{shadows} the
existing binding.
@ -65,18 +65,18 @@ existing binding.
(f list)
]
Even identifiers like @scheme[define] and @scheme[lambda] get their
Even identifiers like @racket[define] and @racket[lambda] get their
meanings from bindings, though they have @defterm{transformer}
bindings (which means that they indicate syntactic forms) instead of
value bindings. Since @scheme[define] has a transformer binding, the
identifier @schemeidfont{define} cannot be used by itself to get a
value. However, the normal binding for @schemeidfont{define} can be
value bindings. Since @racket[define] has a transformer binding, the
identifier @racketidfont{define} cannot be used by itself to get a
value. However, the normal binding for @racketidfont{define} can be
shadowed.
@examples[
define
(eval:alts (let ([@#,schemeidfont{define} 5]) @#,schemeidfont{define}) (let ([define 5]) define))
(eval:alts (let ([@#,racketidfont{define} 5]) @#,racketidfont{define}) (let ([define 5]) define))
]
Shadowing standard bindings in this way is rarely a good idea, but the
possibility is an inherent part of Scheme's flexibility.
possibility is an inherent part of Racket's flexibility.

View File

@ -5,15 +5,15 @@
@title[#:tag "booleans"]{Booleans}
Scheme has two distinguished constants to represent boolean values:
@scheme[#t] for true and @scheme[#f] for false. Uppercase
@schemevalfont{#T} and @schemevalfont{#F} are parsed as the same
Racket has two distinguished constants to represent boolean values:
@racket[#t] for true and @racket[#f] for false. Uppercase
@racketvalfont{#T} and @racketvalfont{#F} are parsed as the same
values, but the lowercase forms are preferred.
The @scheme[boolean?] procedure recognizes the two boolean
constants. In the result of a test expression for @scheme[if],
@scheme[cond], @scheme[and], @scheme[or], etc., however, any value
other than @scheme[#f] counts as true.
The @racket[boolean?] procedure recognizes the two boolean
constants. In the result of a test expression for @racket[if],
@racket[cond], @racket[and], @racket[or], etc., however, any value
other than @racket[#f] counts as true.
@examples[
(= 2 (+ 1 1))

View File

@ -5,8 +5,8 @@
@title[#:tag "bytestrings"]{Bytes and Byte Strings}
A @deftech{byte} is an exact integer between @scheme[0] and
@scheme[255], inclusive. The @scheme[byte?] predicate recognizes
A @deftech{byte} is an exact integer between @racket[0] and
@racket[255], inclusive. The @racket[byte?] predicate recognizes
numbers that represent bytes.
@examples[
@ -36,23 +36,23 @@ b
b
]
The @scheme[display] form of a byte string writes its raw bytes to the
The @racket[display] form of a byte string writes its raw bytes to the
current output port (see @secref["i/o"]). Technically,
@scheme[display] of a normal (i.e,. character) string prints the UTF-8
@racket[display] of a normal (i.e,. character) string prints the UTF-8
encoding of the string to the current output port, since output is
ultimately defined in terms of bytes; @scheme[display] of a byte
ultimately defined in terms of bytes; @racket[display] of a byte
string, however, writes the raw bytes with no encoding. Along the same
lines, when this documentation shows output, it technically shows the
UTF-8-decoded form of the output.
@examples[
(display #"Apple")
(eval:alts (code:line (display @#,schemevalfont{"\316\273"}) (code:comment @#,t{same as @scheme["\316\273"]}))
(eval:alts (code:line (display @#,racketvalfont{"\316\273"}) (code:comment @#,t{same as @racket["\316\273"]}))
(display "\316\273"))
(code:line (display #"\316\273") (code:comment @#,t{UTF-8 encoding of @elem["\u03BB"]}))
]
For explicitly converting between strings and byte strings, Scheme
For explicitly converting between strings and byte strings, Racket
supports three kinds of encodings directly: UTF-8, Latin-1, and the
current locale's encoding. General facilities for byte-to-byte
conversions (especially to and from UTF-8) fill the gap to support

View File

@ -2,25 +2,25 @@
@(require scribble/manual
scribble/eval
"guide-utils.ss"
(for-label scheme/match))
(for-label racket/match))
@title[#:tag "case"]{Simple Dispatch: @scheme[case]}
@title[#:tag "case"]{Simple Dispatch: @racket[case]}
The @scheme[case] form dispatches to a clause by matching the result
The @racket[case] form dispatches to a clause by matching the result
of an expression to the values for the clause:
@specform[(case expr
[(datum ...+) expr ...+]
...)]
Each @scheme[_datum] will be compared to the result of the first
@scheme[_expr] using @scheme[eqv?]. Since @scheme[eqv?] doesn't work on
many kinds of values, notably strings and lists, each @scheme[_datum]
Each @racket[_datum] will be compared to the result of the first
@racket[_expr] using @racket[eqv?]. Since @racket[eqv?] doesn't work on
many kinds of values, notably strings and lists, each @racket[_datum]
is typically a number, symbol, or boolean.
Multiple @scheme[_datum]s can be supplied for each clause, and the
corresponding @scheme[_expr] is evaluated of any of the
@scheme[_datum]s match.
Multiple @racket[_datum]s can be supplied for each clause, and the
corresponding @racket[_expr] is evaluated of any of the
@racket[_datum]s match.
@examples[
(let ([v (random 6)])
@ -32,8 +32,8 @@ corresponding @scheme[_expr] is evaluated of any of the
[(3 4 5) 'many]))
]
The last clause of a @scheme[case] form can use @scheme[else], just
like @scheme[cond]:
The last clause of a @racket[case] form can use @racket[else], just
like @racket[cond]:
@examples[
(case (random 6)
@ -43,5 +43,5 @@ like @scheme[cond]:
[else 'many])
]
For more general pattern matching, use @scheme[match], which is
For more general pattern matching, use @racket[match], which is
introduced in @secref["match"].

View File

@ -17,25 +17,25 @@ shown with @litchar{\u} when the string is printed.
@refdetails/gory["parse-string"]{the syntax of strings}
The @scheme[display] procedure directly writes the characters of a
The @racket[display] procedure directly writes the characters of a
string to the current output port (see @secref["i/o"]), in contrast
to the string-constant syntax used to print a string result.
@examples[
"Apple"
(eval:alts @#,schemevalfont{"\u03BB"} "\u03BB")
(eval:alts @#,racketvalfont{"\u03BB"} "\u03BB")
(display "Apple")
(display "a \"quoted\" thing")
(display "two\nlines")
(eval:alts (display @#,schemevalfont{"\u03BB"}) (display "\u03BB"))
(eval:alts (display @#,racketvalfont{"\u03BB"}) (display "\u03BB"))
]
A string can be mutable or immutable; strings written directly as
expressions are immutable, but most other strings are mutable. The
@scheme[make-string] procedure creates a mutable string given a length
and optional fill character. The @scheme[string-ref] procedure
@racket[make-string] procedure creates a mutable string given a length
and optional fill character. The @racket[string-ref] procedure
accesses a character from a string (with 0-based indexing); the
@scheme[string-set!] procedure changes a character in a mutable
@racket[string-set!] procedure changes a character in a mutable
string.
@examples[
@ -51,9 +51,9 @@ String ordering and case operations are generally
users. A few @defterm{locale-dependent} operations are provided that
allow the way that strings are case-folded and sorted to depend on the
end-user's locale. If you're sorting strings, for example, use
@scheme[string<?] or @scheme[string-ci<?] if the sort result should be
consistent across machines and users, but use @scheme[string-locale<?]
or @scheme[string-locale-ci<?] if the sort is purely to order strings
@racket[string<?] or @racket[string-ci<?] if the sort result should be
consistent across machines and users, but use @racket[string-locale<?]
or @racket[string-locale-ci<?] if the sort is purely to order strings
for an end user.
@examples[

View File

@ -5,7 +5,7 @@
@title[#:tag "characters"]{Characters}
A Scheme @deftech{character} corresponds to a Unicode @defterm{scalar
A Racket @deftech{character} corresponds to a Unicode @defterm{scalar
value}. Roughly, a scalar value is an unsigned integer whose
representation fits into 21 bits, and that maps to some notion of a
natural-language character or piece of a character. Technically, a
@ -14,17 +14,17 @@ scalar value is a simpler notion than the concept called a
works well for many purposes. For example, any accented Roman letter
can be represented as a scalar value, as can any common Chinese character.
Although each Scheme character corresponds to an integer, the
Although each Racket character corresponds to an integer, the
character datatype is separate from numbers. The
@scheme[char->integer] and @scheme[integer->char] procedures convert
@racket[char->integer] and @racket[integer->char] procedures convert
between scalar-value numbers and the corresponding character.
A printable character normally prints as @litchar{#\} followed
by the represented character. An unprintable character normally prints
as @litchar{#\u} followed by the scalar value as hexadecimal
number. A few characters are printed specially; for example, the space
and linefeed characters print as @scheme[#\space] and
@scheme[#\newline], respectively.
and linefeed characters print as @racket[#\space] and
@racket[#\newline], respectively.
@refdetails/gory["parse-character"]{the syntax of characters}
@ -32,12 +32,12 @@ and linefeed characters print as @scheme[#\space] and
(integer->char 65)
(char->integer #\A)
#\u03BB
(eval:alts @#,schemevalfont["#\\u03BB"] #\u03BB)
(eval:alts @#,racketvalfont["#\\u03BB"] #\u03BB)
(integer->char 17)
(char->integer #\space)
]
The @scheme[display] procedure directly writes a character to the
The @racket[display] procedure directly writes a character to the
current output port (see @secref["i/o"]), in contrast to the
character-constant syntax used to print a character result.
@ -46,7 +46,7 @@ character-constant syntax used to print a character result.
(display #\A)
]
Scheme provides several classification and conversion procedures on
Racket provides several classification and conversion procedures on
characters. Beware, however, that conversions on some Unicode
characters work as a human would expect only when they are in a string
(e.g., upcasing ``@elem["\uDF"]'' or downcasing ``@elem["\u03A3"]'').
@ -59,10 +59,10 @@ characters work as a human would expect only when they are in a string
(char-upcase #\uDF)
]
The @scheme[char=?] procedure compares two or more characters, and
@scheme[char-ci=?] compares characters ignoring case. The
@scheme[eqv?] and @scheme[equal?] procedures behave the same as
@scheme[char=?] on characters; use @scheme[char=?] when you want to
The @racket[char=?] procedure compares two or more characters, and
@racket[char-ci=?] compares characters ignoring case. The
@racket[eqv?] and @racket[equal?] procedures behave the same as
@racket[char=?] on characters; use @racket[char=?] when you want to
more specifically declare that the values being compared are
characters.

View File

@ -5,18 +5,18 @@
@title[#:tag "conditionals"]{Conditionals}
Most functions used for branching, such as @scheme[<] and
@scheme[string?], produce either @scheme[#t] or @scheme[#f]. Scheme's
branching forms, however, treat any value other than @scheme[#f] as
Most functions used for branching, such as @racket[<] and
@racket[string?], produce either @racket[#t] or @racket[#f]. Racket's
branching forms, however, treat any value other than @racket[#f] as
true. We say a @defterm{true value} to mean any value other than
@scheme[#f].
@racket[#f].
This convention for ``true value'' meshes well with protocols where
@scheme[#f] can serve as failure or to indicate that an optional value
@racket[#f] can serve as failure or to indicate that an optional value
is not supplied. (Beware of overusing this trick, and remember that an
exception is usually a better mechanism to report failure.)
For example, the @scheme[member] function serves double duty; it can
For example, the @racket[member] function serves double duty; it can
be used to find the tail of a list that starts with a particular item,
or it can be used to simply check whether an item is present in a
list:
@ -33,46 +33,46 @@ list:
]
@;------------------------------------------------------------------------
@section{Simple Branching: @scheme[if]}
@section{Simple Branching: @racket[if]}
@refalso["if"]{@scheme[if]}
@refalso["if"]{@racket[if]}
In an @scheme[if] form,
In an @racket[if] form,
@specform[(if test-expr then-expr else-expr)]
the @scheme[_test-expr] is always evaluated. If it produces any value
other than @scheme[#f], then @scheme[_then-expr] is
evaluated. Otherwise, @scheme[_else-expr] is evaluated.
the @racket[_test-expr] is always evaluated. If it produces any value
other than @racket[#f], then @racket[_then-expr] is
evaluated. Otherwise, @racket[_else-expr] is evaluated.
An @scheme[if] form must have both a @scheme[_then-expr] and an
@scheme[_else-expr]; the latter is not optional. To perform (or skip)
side-effects based on a @scheme[_test-expr], use @scheme[when] or
@scheme[unless], which we describe later in @secref["begin"].
An @racket[if] form must have both a @racket[_then-expr] and an
@racket[_else-expr]; the latter is not optional. To perform (or skip)
side-effects based on a @racket[_test-expr], use @racket[when] or
@racket[unless], which we describe later in @secref["begin"].
@;------------------------------------------------------------------------
@section[#:tag "and+or"]{Combining Tests: @scheme[and] and @scheme[or]}
@section[#:tag "and+or"]{Combining Tests: @racket[and] and @racket[or]}
@refalso["if"]{@scheme[and] and @scheme[or]}
@refalso["if"]{@racket[and] and @racket[or]}
Scheme's @scheme[and] and @scheme[or] are syntactic forms, rather than
functions. Unlike a function, the @scheme[and] and @scheme[or] forms
Racket's @racket[and] and @racket[or] are syntactic forms, rather than
functions. Unlike a function, the @racket[and] and @racket[or] forms
can skip evaluation of later expressions if an earlier one determines
the answer.
@specform[(and expr ...)]
An @scheme[and] form produces @scheme[#f] if any of its @scheme[_expr]s
produces @scheme[#f]. Otherwise, it produces the value of its last
@scheme[_expr]. As a special case, @scheme[(and)] produces
@scheme[#t].
An @racket[and] form produces @racket[#f] if any of its @racket[_expr]s
produces @racket[#f]. Otherwise, it produces the value of its last
@racket[_expr]. As a special case, @racket[(and)] produces
@racket[#t].
@specform[(or expr ...)]
The @scheme[or] form produces @scheme[#f] if all of its
@scheme[_expr]s produce @scheme[#f]. Otherwise, it produces the first
non-@scheme[#f] value from its @scheme[expr]s. As a special case,
@scheme[(or)] produces @scheme[#f].
The @racket[or] form produces @racket[#f] if all of its
@racket[_expr]s produce @racket[#f]. Otherwise, it produces the first
non-@racket[#f] value from its @racket[expr]s. As a special case,
@racket[(or)] produces @racket[#f].
@examples[
(code:line
@ -84,39 +84,39 @@ non-@scheme[#f] value from its @scheme[expr]s. As a special case,
(got-milk? '(apple milk banana))
]
If evaluation reaches the last @scheme[_expr] of an @scheme[and] or
@scheme[or] form, then the @scheme[_expr]'s value directly determines
the @scheme[and] or @scheme[or] result. Therefore, the last
@scheme[_expr] is in tail position, which means that the above
@scheme[got-milk?] function runs in constant space.
If evaluation reaches the last @racket[_expr] of an @racket[and] or
@racket[or] form, then the @racket[_expr]'s value directly determines
the @racket[and] or @racket[or] result. Therefore, the last
@racket[_expr] is in tail position, which means that the above
@racket[got-milk?] function runs in constant space.
@guideother{@secref["tail-recursion"] introduces tail calls and tail positions.}
@;------------------------------------------------------------------------
@section[#:tag "cond"]{Chaining Tests: @scheme[cond]}
@section[#:tag "cond"]{Chaining Tests: @racket[cond]}
The @scheme[cond] form chains a series of tests to select a result
expression. To a first approximation, the syntax of @scheme[cond] is
The @racket[cond] form chains a series of tests to select a result
expression. To a first approximation, the syntax of @racket[cond] is
as follows:
@refalso["if"]{@scheme[cond]}
@refalso["if"]{@racket[cond]}
@specform[(cond [test-expr expr ...+]
...)]
Each @scheme[_test-expr] is evaluated in order. If it produces
@scheme[#f], the corresponding @scheme[_expr]s are ignored, and
evaluation proceeds to the next @scheme[_test-expr]. As soon as a
@scheme[_test-expr] produces a true value, its @scheme[_text-expr]s
are evaluated to produce the result for the @scheme[cond] form, and no
further @scheme[_test-expr]s are evaluated.
Each @racket[_test-expr] is evaluated in order. If it produces
@racket[#f], the corresponding @racket[_expr]s are ignored, and
evaluation proceeds to the next @racket[_test-expr]. As soon as a
@racket[_test-expr] produces a true value, its @racket[_text-expr]s
are evaluated to produce the result for the @racket[cond] form, and no
further @racket[_test-expr]s are evaluated.
The last @scheme[_test-expr] in a @scheme[cond] can be replaced by
@scheme[else]. In terms of evaluation, @scheme[else] serves as a
synonym for @scheme[#t], but it clarifies that the last clause is
meant to catch all remaining cases. If @scheme[else] is not used, then
it is possible that no @scheme[_test-expr]s produce a true value; in
that case, the result of the @scheme[cond] expression is
The last @racket[_test-expr] in a @racket[cond] can be replaced by
@racket[else]. In terms of evaluation, @racket[else] serves as a
synonym for @racket[#t], but it clarifies that the last clause is
meant to catch all remaining cases. If @racket[else] is not used, then
it is possible that no @racket[_test-expr]s produce a true value; in
that case, the result of the @racket[cond] expression is
@|void-const|.
@examples[
@ -140,7 +140,7 @@ that case, the result of the @scheme[cond] expression is
(got-milk? '(apple milk banana))
]
The full syntax of @scheme[cond] includes two more kinds of clauses:
The full syntax of @racket[cond] includes two more kinds of clauses:
@specform/subs[#:literals (else =>)
(cond cond-clause ...)
@ -149,9 +149,9 @@ The full syntax of @scheme[cond] includes two more kinds of clauses:
[test-expr => proc-expr]
[test-expr]])]
The @scheme[=>] variant captures the true result of its
@scheme[_test-expr] and passes it to the result of the
@scheme[_proc-expr], which must be a function of one argument.
The @racket[=>] variant captures the true result of its
@racket[_test-expr] and passes it to the result of the
@racket[_proc-expr], which must be a function of one argument.
@examples[
(define (after-groucho lst)
@ -163,6 +163,6 @@ The @scheme[=>] variant captures the true result of its
(after-groucho '("Harpo" "Zeppo"))
]
A clause that includes only a @scheme[_test-expr] is rarely used. It
captures the true result of the @scheme[_test-expr], and simply
returns the result for the whole @scheme[cond] expression.
A clause that includes only a @racket[_test-expr] is rarely used. It
captures the true result of the @racket[_test-expr], and simply
returns the result for the whole @racket[cond] expression.

View File

@ -3,12 +3,12 @@
scribble/eval
"guide-utils.ss"
"contracts-utils.ss"
(for-label scheme/contract)
(for-label scheme/gui))
(for-label racket/contract)
(for-label racket/gui))
@title[#:tag "contracts-examples"]{Examples}
This section illustrates the current state of PLT Scheme's contract
This section illustrates the current state of Racket's contract
implementation with a series of examples from @italic{Design by
Contract, by Example} @cite["Mitchell02"].
@ -51,8 +51,8 @@ Each of the following sections corresponds to a chapter in
Mitchell and McKim use Eiffel as the underlying programming language and
employ a conventional imperative programming style. Our long-term goal is
to transliterate their examples into applicative Scheme,
structure-oriented imperative Scheme, and PLT Scheme's class system.
to transliterate their examples into applicative Racket,
structure-oriented imperative Racket, and Racket's class system.
Note: To mimic Mitchell and McKim's informal notion of parametericity
(parametric polymorphism), we use first-class contracts. At several

View File

@ -4,8 +4,8 @@
"guide-utils.ss"
"contracts-utils.ss"
(for-label framework/framework)
(for-label scheme/contract)
(for-label scheme/gui))
(for-label racket/contract)
(for-label racket/gui))
@title[#:tag "contracts-general-functions"]{Contracts on Functions in General}
@ -14,8 +14,8 @@
You wrote your module. You added contracts. You put them into the interface
so that client programmers have all the information from interfaces. It's a
piece of art:
@schememod[
scheme
@racketmod[
racket
(provide/contract
[deposit (-> (lambda (x)
@ -30,24 +30,24 @@ Several clients used your module. Others used their
modules in turn. And all of a sudden one of them sees this error
message:
@inset-flow{@schemeerror{bank-client broke the contract (-> ??? any)
@inset-flow{@racketerror{bank-client broke the contract (-> ??? any)
it had with myaccount on deposit; expected <???>, given: -10}}
Clearly, @scheme[bank-client] is a module that uses @scheme[myaccount]
but what is the @schemeerror{???} doing there? Wouldn't it be nice if
Clearly, @racket[bank-client] is a module that uses @racket[myaccount]
but what is the @racketerror{???} doing there? Wouldn't it be nice if
we had a name for this class of data much like we have string, number,
and so on?
For this situation, PLT Scheme provides @deftech{flat named
For this situation, Racket provides @deftech{flat named
contracts}. The use of ``contract'' in this term shows that contracts
are first-class values. The ``flat'' means that the collection of data
is a subset of the built-in atomic classes of data; they are described
by a predicate that consumes all Scheme values and produces a
by a predicate that consumes all Racket values and produces a
boolean. The ``named'' part says what we want to do, which is to name
the contract so that error messages become intelligible:
@schememod[
scheme
@racketmod[
racket
(define (amount? x) (and (number? x) (integer? x) (>= x 0)))
(define amount (flat-named-contract 'amount amount?))
@ -62,16 +62,16 @@ scheme
With this little change, the error message becomes all of the
sudden quite readable:
@inset-flow{@schemeerror{bank-client broke the contract (-> amount
@inset-flow{@racketerror{bank-client broke the contract (-> amount
any) it had with myaccount on deposit; expected <amount>, given: -10}}
@ctc-section[#:tag "optional"]{Optional Arguments}
Take a look at this excerpt from a string-processing module, inspired by the
@link["http://schemecookbook.org"]{Scheme cookbook}:
@link["http://racketcookbook.org"]{Racket cookbook}:
@schememod[
scheme
@racketmod[
racket
(provide/contract
(code:comment @#,t{pad the given str left and right with})
@ -89,28 +89,28 @@ scheme
(build-string rmargin (λ (x) pad))))
]
The module exports @scheme[string-pad-center], a function
that creates a string of a given @scheme[width] with the
The module exports @racket[string-pad-center], a function
that creates a string of a given @racket[width] with the
given string in the center. The default fill character is
@scheme[#\space]; if the client module wishes to use a
different character, it may call @scheme[string-pad-center]
with a third argument, a @scheme[char], overwriting the
@racket[#\space]; if the client module wishes to use a
different character, it may call @racket[string-pad-center]
with a third argument, a @racket[char], overwriting the
default.
The function definition uses optional arguments, which is
appropriate for this kind of functionality. The interesting
point here is the formulation of the contract for the
@scheme[string-pad-center].
@racket[string-pad-center].
The contract combinator @scheme[->*], demands several groups of contracts:
The contract combinator @racket[->*], demands several groups of contracts:
@itemize[
@item{The first one is a parenthesized group of contracts for all required
arguments. In this example, we see two: @scheme[string?] and
@scheme[natural-number/c]. }
arguments. In this example, we see two: @racket[string?] and
@racket[natural-number/c]. }
@item{The second one is a parenthesized group of contracts for all optional
arguments: @scheme[char?]. }
arguments: @racket[char?]. }
@item{The last one is a single contract: the result of the function.}
]
@ -123,41 +123,41 @@ arguments: @scheme[char?]. }
@ctc-section[#:tag "rest-args"]{Rest Arguments}
We all know that @scheme[+] in Beginner Scheme is a function
We all know that @racket[+] in Beginner Racket is a function
that consumes at least two numbers but, in principle,
arbitrarily many more. Defining the function is easy:
@schemeblock[
@racketblock[
(define (plus fst snd . rst)
(foldr + (+ fst snd) rst))
]
Describing this function via a contract is difficult because of the rest
argument (@scheme[rst]).
argument (@racket[rst]).
Here is the contract:
@schemeblock[
@racketblock[
(provide/contract
[plus (->* (number? number?) () #:rest (listof number?) number?)])
]
The @scheme[->*] contract combinator empowers you to specify
The @racket[->*] contract combinator empowers you to specify
functions that consume a variable number of arguments or functions like
@scheme[plus], which consume ``at least this number'' of arguments but
@racket[plus], which consume ``at least this number'' of arguments but
an arbitrary number of additional arguments.
The contracts for the required arguments are enclosed in the first
pair of parentheses:
@schemeblock[
@racketblock[
(number? number?)
]
For @scheme[plus] they demand two numbers. The empty pair of
For @racket[plus] they demand two numbers. The empty pair of
parenthesis indicates that there are no optional arguments
(not counting the rest arguments) and the contract for the
rest argument follows @scheme[#:rest]
@schemeblock[
rest argument follows @racket[#:rest]
@racketblock[
(listof number?)
]
Since the remainder of the actual arguments are collected
in a list for a rest parameter such as @scheme[rst], the
in a list for a rest parameter such as @racket[rst], the
contract demands a list of values; in this specific
examples, these values must be numbers.
@ -165,12 +165,12 @@ rest argument follows @scheme[#:rest]
Sometimes, a function accepts many arguments and remembering
their order can be a nightmare. To help with such functions,
PLT Scheme has @seclink["lambda-keywords"]{keyword} arguments.
Racket has @seclink["lambda-keywords"]{keyword} arguments.
For example, consider this function that creates a simple
GUI and asks the user a yes-or-no question:
@schememod[
scheme/gui
@racketmod[
racket/gui
(define (ask-yes-or-no-question #:question question
#:default answer
@ -203,31 +203,31 @@ scheme/gui
]
@margin-note{Note that if you really want to ask a yes-or-no
question via a GUI, you should use
@scheme[message-box/custom] (and generally speaking,
@racket[message-box/custom] (and generally speaking,
avoiding the responses ``yes'' and ``no'' in your dialog is a
good idea, too ...).}
The contract for @scheme[ask-yes-or-no-question] uses our
old friend the @scheme[->] contract combinator. Just like
@scheme[lambda] (or @scheme[define]-based functions) use
The contract for @racket[ask-yes-or-no-question] uses our
old friend the @racket[->] contract combinator. Just like
@racket[lambda] (or @racket[define]-based functions) use
keywords for specifying keyword arguments, it uses keywords
for specifying contracts on keyword arguments. In this case,
it says that @scheme[ask-yes-or-no-question] must receive
it says that @racket[ask-yes-or-no-question] must receive
five keyword arguments, one for each of the keywords
@scheme[#:question],
@scheme[#:default],
@scheme[#:title],
@scheme[#:width], and
@scheme[#:height].
@racket[#:question],
@racket[#:default],
@racket[#:title],
@racket[#:width], and
@racket[#:height].
Also, just like in a function definition, the keywords in
the @scheme[->] may appear in any order.
the @racket[->] may appear in any order.
@ctc-section[#:tag "optional-keywords"]{Optional Keyword Arguments}
Of course, many of the parameters in
@scheme[ask-yes-or-no-question] (from the previous question)
@racket[ask-yes-or-no-question] (from the previous question)
have reasonable defaults, and should be made optional:
@schemeblock[
@racketblock[
(define (ask-yes-or-no-question #:question question
#:default answer
#:title [title "Yes or No?"]
@ -237,14 +237,14 @@ have reasonable defaults, and should be made optional:
]
To specify this function's contract, we need to use
@scheme[->*]. It too supports keywords just as you might
@racket[->*]. It too supports keywords just as you might
expect, in both the optional and mandatory argument
sections. In this case, we have mandatory keywords
@scheme[#:question] and @scheme[#:default], and optional keywords
@scheme[#:title],
@scheme[#:width], and
@scheme[#:height]. So, we write the contract like this:
@schemeblock[
@racket[#:question] and @racket[#:default], and optional keywords
@racket[#:title],
@racket[#:width], and
@racket[#:height]. So, we write the contract like this:
@racketblock[
(provide/contract
[ask-yes-or-no-question
(->* (#:question string?
@ -263,8 +263,8 @@ optional ones in the second section.
Here is an excerpt from an imaginary (pardon the pun) numerics module:
@schememod[
scheme
@racketmod[
racket
(provide/contract
[sqrt.v1 (->d ([argument (>=/c 1)])
()
@ -272,22 +272,22 @@ scheme
...
]
The contract for the exported function @scheme[sqrt.v1] uses the
@scheme[->d] rather than @scheme[->] function contract. The ``d''
The contract for the exported function @racket[sqrt.v1] uses the
@racket[->d] rather than @racket[->] function contract. The ``d''
stands for @italic{dependent} contract, meaning the contract for the
function range depends on the value of the argument.
In this particular case, the argument of @scheme[sqrt.v1] is greater
In this particular case, the argument of @racket[sqrt.v1] is greater
or equal to 1. Hence a very basic correctness check is that the result is
smaller than the argument. (Naturally, if this function is critical, one
could strengthen this check with additional clauses.)
In general, a dependent function contract looks just like
the more general @scheme[->*] contract, but with names added
the more general @racket[->*] contract, but with names added
that can be used elsewhere in the contract.
Yes, there are many other contract combinators such as @scheme[<=/c]
and @scheme[>=/c], and it pays off to look them up in the contract
Yes, there are many other contract combinators such as @racket[<=/c]
and @racket[>=/c], and it pays off to look them up in the contract
section of the reference manual. They simplify contracts tremendously
and make them more accessible to potential clients.
@ -299,14 +299,14 @@ course, ordinary accounts don't let customers withdraw an arbitrary amount of
money but only as much as they have in the account.
Suppose the account module provides the following two functions:
@schemeblock[
@racketblock[
balance : (-> account amount)
withdraw : (-> account amount account)
]
Then, informally, the proper precondition for @scheme[withdraw] is that
Then, informally, the proper precondition for @racket[withdraw] is that
``the balance of the given account is greater than or equal to the given (withdrawal) amount.''
The postcondition is similar to the one for
@ctc-link["flat-named-contracts"]{@scheme[deposit]}:
@ctc-link["flat-named-contracts"]{@racket[deposit]}:
``the balance of the resulting account is larger than (or equal to) the one of the
given account.''
You could of course also formulate a full-fledged correctness condition, namely,
@ -315,8 +315,8 @@ one, plus the given amount.
The following module implements accounts imperatively and specifies the
conditions we just discussed:
@schememod[
scheme
@racketmod[
racket
(code:comment "section 1: the contract definitions")
(define-struct account (balance) #:mutable)
@ -359,36 +359,36 @@ scheme
]
The second section is the export interface: @itemize[
@item{@scheme[create] consumes an initial deposit and
@item{@racket[create] consumes an initial deposit and
produces an account. This kind of contract is just like a
type in a statically typed language, except that statically
typed languages usually don't support the type ``natural
numbers'' (as a full-fledged subtype of numbers). }
@item{@scheme[balance] consumes an account and computes its current balance.}
@item{@racket[balance] consumes an account and computes its current balance.}
@item{@scheme[withdraw] consumes an account, named @scheme[acc], and an
amount, @scheme[amt]. In addition to being an @scheme[amount], the
latter must also be less than @scheme[(balance acc)], i.e., the balance of
the given account. That is, the contract for @scheme[amt] depends on the
value of @scheme[acc], which is what the @scheme[->d]
@item{@racket[withdraw] consumes an account, named @racket[acc], and an
amount, @racket[amt]. In addition to being an @racket[amount], the
latter must also be less than @racket[(balance acc)], i.e., the balance of
the given account. That is, the contract for @racket[amt] depends on the
value of @racket[acc], which is what the @racket[->d]
contract combinator expresses.
The result contract is formed on the fly:
@scheme[(mk-account-contract acc amt > msg>)].
@racket[(mk-account-contract acc amt > msg>)].
It is an application of a contract-producing function that
consumes an account, an amount, a comparison operator, and an error message (a
format string). The result is a contract.
}
@item{@scheme[deposit]'s contract has been reformulated using the
@scheme[->d] combinator. }
@item{@racket[deposit]'s contract has been reformulated using the
@racket[->d] combinator. }
]
The code in the first section defines all those pieces that
are needed for the formulation of the export contracts:
@scheme[account?], @scheme[amount], error messages (format
strings), and @scheme[mk-account-contract]. The latter is a
@racket[account?], @racket[amount], error messages (format
strings), and @racket[mk-account-contract]. The latter is a
function that extracts the current balance from the given
account and then returns a named contract, whose error
message (contract name) is a string that refers to this
@ -398,12 +398,12 @@ given comparison operator, than the original balance.
@ctc-section[#:tag "arrow-d-eval-order"]{Ensuring that a Function Properly Modifies State}
The @scheme[->d] contract combinator can also ensure that a
The @racket[->d] contract combinator can also ensure that a
function only modifies state according to certain
constraints. For example, consider this contract
(it is a slightly simplified from the function
@scheme[preferences:add-panel] in the framework):
@schemeblock[
@racket[preferences:add-panel] in the framework):
@racketblock[
(->d ([parent (is-a?/c area-container-window<%>)])
()
[_
@ -414,29 +414,29 @@ constraints. For example, consider this contract
(send parent get-children))))])
]
It says that the function accepts a single argument, named
@scheme[parent], and that @scheme[parent] must be
an object matching the interface @scheme[area-container-window<%>].
@racket[parent], and that @racket[parent] must be
an object matching the interface @racket[area-container-window<%>].
The range contract ensures that the function only modifies
the children of @scheme[parent] by adding a new child to the
the children of @racket[parent] by adding a new child to the
front of the list. It accomplishes this by using the
@scheme[_] instead of a normal identifier, which tells the
@racket[_] instead of a normal identifier, which tells the
contract library that the range contract does not depend on
the values of any of the results, and thus the contract
library evaluates the expression following the @scheme[_]
library evaluates the expression following the @racket[_]
when the function is called, instead of when it
returns. Therefore the call to the @scheme[get-children] method
returns. Therefore the call to the @racket[get-children] method
happens before the function under the contract is called.
When the function under contract returns, its result is
passed in as @scheme[child], and the contract ensures that
passed in as @racket[child], and the contract ensures that
the children after the function return are the same as the
children before the function called, but with one more
child, at the front of the list.
To see the difference in a toy example that focuses
on this point, consider this program
@schememod[
scheme
@racketmod[
racket
(define x '())
(define (get-x) x)
(define (f) (set! x (cons 'f x)))
@ -444,29 +444,29 @@ scheme
[f (->d () () [_ (begin (set! x (cons 'ctc x)) any/c)])]
[get-x (-> (listof symbol?))])
]
If you were to require this module, call @scheme[f], then
the result of @scheme[get-x] would be @scheme['(f ctc)]. In
contrast, if the contract for @scheme[f] were
@schemeblock[(->d () () [res (begin (set! x (cons 'ctc x)) any/c)])]
(only changing the underscore to @scheme[res]), then
the result of @scheme[get-x] would be @scheme['(ctc f)].
If you were to require this module, call @racket[f], then
the result of @racket[get-x] would be @racket['(f ctc)]. In
contrast, if the contract for @racket[f] were
@racketblock[(->d () () [res (begin (set! x (cons 'ctc x)) any/c)])]
(only changing the underscore to @racket[res]), then
the result of @racket[get-x] would be @racket['(ctc f)].
@ctc-section[#:tag "case-lambda"]{Contracts for @scheme[case-lambda]}
@ctc-section[#:tag "case-lambda"]{Contracts for @racket[case-lambda]}
Dybvig, in Chapter 5 of the
@link["http://www.scheme.com/csug/"]{Chez Scheme User's Guide},
@link["http://www.racket.com/csug/"]{Chez Racket User's Guide},
explains the meaning and pragmatics of
@scheme[case-lambda] with the following example (among
@racket[case-lambda] with the following example (among
others):
@schemeblock[
@racketblock[
(define substring1
(case-lambda
[(s) (substring1 s 0 (string-length s))]
[(s start) (substring1 s start (string-length s))]
[(s start end) (substring s start end)]))
]
This version of @scheme[substring] has one of the following signature:
This version of @racket[substring] has one of the following signature:
@itemize[
@item{just a string, in which case it copies the string;}
@item{a string and an index into the string, in which case it extracts the
@ -475,9 +475,9 @@ others):
fragment of the string between the two indices. }
]
The contract for such a function is formed with the @scheme[case->]
The contract for such a function is formed with the @racket[case->]
combinator, which combines as many functional contracts as needed:
@schemeblock[
@racketblock[
(provide/contract
[substring1
(case->
@ -485,19 +485,19 @@ The contract for such a function is formed with the @scheme[case->]
(string? natural-number/c . -> . string?)
(string? natural-number/c natural-number/c . -> . string?))])
]
As you can see, the contract for @scheme[substring1] combines three
As you can see, the contract for @racket[substring1] combines three
function contracts, just as many clauses as the explanation of its
functionality required.
@;{
This isn't supported anymore (yet...?). -robby
In the case of @scheme[substring1], we also know that the indices
In the case of @racket[substring1], we also know that the indices
that it consumes ought to be natural numbers less than the length of the
given string. Since @scheme[case->] just combines arrow contracts,
given string. Since @racket[case->] just combines arrow contracts,
adding such constraints is just a matter of strengthening the individual
contracts:
<scheme>
<racket>
(provide/contract
[substring1 (case->
(string? . -> . string?)
@ -510,17 +510,17 @@ In the case of @scheme[substring1], we also know that the indices
(>=/c a)
(</c (string-length s)))])
string?))])
</scheme>
Here we used @scheme[->r] to name the parameters and express the
</racket>
Here we used @racket[->r] to name the parameters and express the
numeric constraints on them.
}
@ctc-section[#:tag "multiple"]{Multiple Result Values}
The function @scheme[split] consumes a list of @scheme[char]s
The function @racket[split] consumes a list of @racket[char]s
and delivers the string that occurs before the first occurrence of
@scheme[#\newline] (if any) and the rest of the list:
@schemeblock[
@racket[#\newline] (if any) and the rest of the list:
@racketblock[
(define (split l)
(define (split l w)
(cond
@ -534,18 +534,18 @@ The function @scheme[split] consumes a list of @scheme[char]s
traversing a single list.
The contract for such a function can use the ordinary
function arrow @scheme[->], since it
treats @scheme[values] specially, when it appears as the
function arrow @racket[->], since it
treats @racket[values] specially, when it appears as the
last result:
@schemeblock[
@racketblock[
(provide/contract
[split (-> (listof char?)
(values string? (listof char?)))])
]
The contract for such a function can also be written
using @scheme[->*], just like @scheme[plus]:
@schemeblock[
using @racket[->*], just like @racket[plus]:
@racketblock[
(provide/contract
[split (->* ((listof char?))
()
@ -555,13 +555,13 @@ using @scheme[->*], just like @scheme[plus]:
extra pair of parentheses (and must always be wrapped like
that) and the empty pair of parentheses indicates that
there are no optoinal arguments. The contracts for the
results are inside @scheme[values]: a string and a list of
results are inside @racket[values]: a string and a list of
characters.
Now suppose we also want to ensure that the first result of
@scheme[split] is a prefix of the given word in list format. In that
case, we need to use the @scheme[->d] contract combinator:
@schemeblock[
@racket[split] is a prefix of the given word in list format. In that
case, we need to use the @racket[->d] contract combinator:
@racketblock[
(define (substring-of? s)
(flat-named-contract
(format "substring of ~s" s)
@ -576,24 +576,24 @@ Now suppose we also want to ensure that the first result of
(values [s (substring-of (list->string fl))]
[c (listof char?)]))])
]
Like @scheme[->*], the @scheme[->d] combinator uses a function over the
Like @racket[->*], the @racket[->d] combinator uses a function over the
argument to create the range contracts. Yes, it doesn't just return one
contract but as many as the function produces values: one contract per
value. In this case, the second contract is the same as before, ensuring
that the second result is a list of @scheme[char]s. In contrast, the
that the second result is a list of @racket[char]s. In contrast, the
first contract strengthens the old one so that the result is a prefix of
the given word.
This contract is expensive to check of course. Here is a slightly
cheaper version:
@schemeblock[
@racketblock[
(provide/contract
[split (->d ([fl (listof char?)])
()
(values [s (string-len/c (length fl))]
[c (listof char?)]))])
]
Click on @scheme[string-len/c] to see what it does.
Click on @racket[string-len/c] to see what it does.
@ctc-section[#:tag "no-domain"]{Procedures of Some Fixed, but Statically Unknown Arity}
@ -602,8 +602,8 @@ function and a list of numbers that eventually applies the former to the
latter. Unless the arity of the given function matches the length of the
given list, your procedure is in trouble.
Consider this @scheme[n-step] function:
@schemeblock[
Consider this @racket[n-step] function:
@racketblock[
(code:comment "(number ... -> (union #f number?)) (listof number) -> void")
(define (n-step proc inits)
(let ([inc (apply proc inits)])
@ -611,15 +611,15 @@ Consider this @scheme[n-step] function:
(n-step proc (map (λ (x) (+ x inc)) inits)))))
]
The argument of @scheme[n-step] is @scheme[proc], a function
@scheme[proc] whose results are either numbers or false, and a list. It
then applies @scheme[proc] to the list @scheme[inits]. As long as
@scheme[proc] returns a number, @scheme[n-step] treats that number
as an increment for each of the numbers in @scheme[inits] and
recurs. When @scheme[proc] returns @scheme[false], the loop stops.
The argument of @racket[n-step] is @racket[proc], a function
@racket[proc] whose results are either numbers or false, and a list. It
then applies @racket[proc] to the list @racket[inits]. As long as
@racket[proc] returns a number, @racket[n-step] treats that number
as an increment for each of the numbers in @racket[inits] and
recurs. When @racket[proc] returns @racket[false], the loop stops.
Here are two uses:
@schemeblock[
@racketblock[
(code:comment "nat -> nat")
(define (f x)
(printf "~s\n" x)
@ -635,28 +635,28 @@ Here are two uses:
(n-step g '(1 1))
]
A contract for @scheme[n-step] must specify two aspects of
@scheme[proc]'s behavior: its arity must include the number of elements
in @scheme[inits], and it must return either a number or
@scheme[#f]. The latter is easy, the former is difficult. At first
A contract for @racket[n-step] must specify two aspects of
@racket[proc]'s behavior: its arity must include the number of elements
in @racket[inits], and it must return either a number or
@racket[#f]. The latter is easy, the former is difficult. At first
glance, this appears to suggest a contract that assigns a
@italic{variable-arity} to @scheme[proc]:
@schemeblock[
@italic{variable-arity} to @racket[proc]:
@racketblock[
(->* ()
(listof any/c)
(or/c number? false/c))
]
This contract, however, says that the function must accept @emph{any}
number of arguments, not a @emph{specific} but
@emph{undetermined} number. Thus, applying @scheme[n-step] to
@scheme[(lambda (x) x)] and @scheme[(list 1)] breaks the contract
@emph{undetermined} number. Thus, applying @racket[n-step] to
@racket[(lambda (x) x)] and @racket[(list 1)] breaks the contract
because the given function accepts only one argument.
The correct contract uses the @scheme[unconstrained-domain->]
The correct contract uses the @racket[unconstrained-domain->]
combinator, which specifies only the range of a function, not its
domain. It is then possible to combine this contract with an arity test to
specify the correct @scheme[n-step]'s contract:
@schemeblock[
specify the correct @racket[n-step]'s contract:
@racketblock[
(provide/contract
[n-step
(->d ([proc

View File

@ -6,7 +6,7 @@
@title[#:tag "datatypes" #:style 'toc]{Built-In Datatypes}
The @seclink["to-scheme"]{previous chapter} introduced some of
Scheme's built-in datatypes: numbers, booleans, strings, lists, and
Racket's built-in datatypes: numbers, booleans, strings, lists, and
procedures. This section provides a more complete coverage of the
built-in datatypes for simple forms of data.

View File

@ -2,7 +2,8 @@
@(require scribble/manual
scribble/eval
scribble/bnf
"guide-utils.ss")
"guide-utils.ss"
(for-label racket/serialize))
@(define posn-eval (make-base-eval))
@ -10,55 +11,46 @@
@refalso["structures"]{structure types}
New datatypes are normally created with the @scheme[define-struct]
New datatypes are normally created with the @scheme[struct]
form, which is the topic of this chapter. The class-based object
system, which we defer to @secref["classes"], offers an alternate
mechanism for creating new datatypes, but even classes and objects are
implemented in terms of structure types.
@; ------------------------------------------------------------
@section{Simple Structure Types: @scheme[define-struct]}
@section{Simple Structure Types: @scheme[struct]}
@refalso["define-struct"]{@scheme[define-struct]}
@refalso["define-struct"]{@scheme[struct]}
To a first approximation, the syntax of @scheme[define-struct] is
To a first approximation, the syntax of @scheme[struct] is
@specform[
(define-struct struct-id (field-id ...))
(struct struct-id (field-id ...))
]{}
A @scheme[define-struct] declaration binds @scheme[_struct-id], but
only to static information about the structure type that cannot be
used directly:
@def+int[
@as-examples[@schemeblock+eval[
#:eval posn-eval
(define-struct posn (x y))
posn
]
(struct posn (x y))
]]
We show two uses of the @scheme[_struct-id] binding below in
@secref["struct-copy"] and @secref["struct-subtypes"].
Meanwhile, in addition to defining @scheme[_struct-id],
@scheme[define-struct] also defines a number of identifiers that are
built from @scheme[_struct-id] and the @scheme[_field-id]s:
The @scheme[struct] form binds @scheme[_struct-id] and a number of
identifiers that are built from @scheme[_struct-id] and the
@scheme[_field-id]s:
@itemize[
@item{@schemeidfont{make-}@scheme[_struct-id] : a
@deftech{constructor} function that takes as many arguments as
the number of @scheme[_field-id]s, and returns an instance of
the structure type.
@item{@scheme[_struct-id] : a @deftech{constructor} function that
takes as many arguments as the number of @scheme[_field-id]s,
and returns an instance of the structure type.
@examples[#:eval posn-eval (make-posn 1 2)]}
@examples[#:eval posn-eval (posn 1 2)]}
@item{@scheme[_struct-id]@schemeidfont{?} : a @deftech{predicate}
function that takes a single argument and returns @scheme[#t]
if it is an instance of the structure type, @scheme[#f]
otherwise.
@examples[#:eval posn-eval (posn? 3) (posn? (make-posn 1 2))]}
@examples[#:eval posn-eval (posn? 3) (posn? (posn 1 2))]}
@item{@scheme[_struct-id]@schemeidfont{-}@scheme[_field-id] : for
each @scheme[_field-id], an @deftech{accessor} that extracts
@ -66,7 +58,7 @@ built from @scheme[_struct-id] and the @scheme[_field-id]s:
structure type.
@examples[#:eval posn-eval
(posn-x (make-posn 1 2)) (posn-y (make-posn 1 2))]}
(posn-x (posn 1 2)) (posn-y (posn 1 2))]}
@item{@schemeidfont{struct:}@scheme[_struct-id] : a
@deftech{structure type descriptor}, which is a value that
@ -76,9 +68,9 @@ built from @scheme[_struct-id] and the @scheme[_field-id]s:
]
A @scheme[define-struct] form places no constraints on the kinds of
A @scheme[struct] form places no constraints on the kinds of
values that can appear for fields in an instance of the structure
type. For example, @scheme[(make-posn "apple" #f)] produces an
type. For example, @scheme[(posn "apple" #f)] produces an
instance of @scheme[posn], even though @scheme["apple"] and
@scheme[#f] are not valid coordinates for the obvious uses of
@scheme[posn] instances. Enforcing constraints on field values, such
@ -99,7 +91,7 @@ modified.
]
The @scheme[_struct-id] that appears after @scheme[struct-copy] must
be a structure type name bound by @scheme[define-struct] (i.e., the
be a structure type name bound by @scheme[struct] (i.e., the
name that cannot be used directly as an expression). The
@scheme[_struct-expr] must produce an instance of the structure type.
The result is a new instance of the structure tpe that is like the old
@ -108,7 +100,7 @@ the value of the corresponding @scheme[_expr].
@examples[
#:eval posn-eval
(define p1 (make-posn 1 2))
(define p1 (posn 1 2))
(define p2 (struct-copy posn p1 [x 3]))
(list (posn-x p2) (posn-y p2))
(list (posn-x p1) (posn-x p2))
@ -118,22 +110,22 @@ the value of the corresponding @scheme[_expr].
@; ------------------------------------------------------------
@section[#:tag "struct-subtypes"]{Structure Subtypes}
An extended form of @scheme[define-struct] can be used to define a
An extended form of @scheme[struct] can be used to define a
@defterm{structure subtype}, which is a structure type that extends an
existing structure type:
@specform[
(define-struct (struct-id super-id) (field-id ...))
(struct struct-id super-id (field-id ...))
]
The @scheme[_super-id] must be a structure type name bound by
@scheme[define-struct] (i.e., the name that cannot be used directly as
@scheme[struct] (i.e., the name that cannot be used directly as
an expression).
@as-examples[@schemeblock+eval[
#:eval posn-eval
(define-struct posn (x y))
(define-struct (3d-posn posn) (z))
(struct posn (x y))
(struct 3d-posn posn (z))
]]
A structure subtype inherits the fields of its supertype, and the
@ -144,7 +136,7 @@ supertype.
@examples[
#:eval posn-eval
(define p (make-3d-posn 1 2 3))
(define p (3d-posn 1 2 3))
p
(posn? p)
(posn-x p)
@ -157,7 +149,7 @@ p
With a structure type definition like
@schemeblock[
(define-struct posn (x y))
(struct posn (x y))
]
an instance of the structure type prints in a way that does not show
@ -171,14 +163,14 @@ To make a structure type @deftech{transparent}, use the
@def+int[
#:eval posn-eval
(define-struct posn (x y)
#:transparent)
(make-posn 1 2)
(struct posn (x y)
#:transparent)
(posn 1 2)
]
An instance of a transparent structure type prints like a vector, and
it shows the content of the structure's fields. A transparent
structure type also allows reflective operations, such as
An instance of a transparent structure type prints like a call to the
constructor, so that it shows the structures field values. A
transparent structure type also allows reflective operations, such as
@scheme[struct?] and @scheme[struct-info], to be used on its instances
(see @secref["reflection"]).
@ -197,15 +189,15 @@ to mere instance identity for opaque structure types:
@def+int[
#:eval posn-eval
(define-struct glass (width height) #:transparent)
(equal? (make-glass 1 2) (make-glass 1 2))
(struct glass (width height) #:transparent)
(equal? (glass 1 2) (glass 1 2))
]
@def+int[
#:eval posn-eval
(define-struct lead (width height))
(define slab (make-lead 1 2))
(struct lead (width height))
(define slab (lead 1 2))
(equal? slab slab)
(equal? slab (make-lead 1 2))
(equal? slab (lead 1 2))
]
To support instances comparisons via @scheme[equal?] without making
@ -214,7 +206,7 @@ keyword, @scheme[prop:equal+hash], and then a list of three functions:
@def+int[
#:eval posn-eval
(define-struct lead (width height)
(struct lead (width height)
#:property
prop:equal+hash
(list (lambda (a b equal?-recur)
@ -229,7 +221,7 @@ keyword, @scheme[prop:equal+hash], and then a list of three functions:
(code:comment @#,t{compute secondary hash code of @scheme[a]})
(+ (hash2-recur (lead-width a))
(hash2-recur (lead-height a))))))
(equal? (make-lead 1 2) (make-lead 1 2))
(equal? (lead 1 2) (lead 1 2))
]
The first function in the list implements the @scheme[equal?] test on
@ -241,9 +233,9 @@ secondary hash codes for use with @tech{hash tables}:
@interaction[
#:eval posn-eval
(define h (make-hash))
(hash-set! h (make-lead 1 2) 3)
(hash-ref h (make-lead 1 2))
(hash-ref h (make-lead 2 1))
(hash-set! h (lead 1 2) 3)
(hash-ref h (lead 1 2))
(hash-ref h (lead 2 1))
]
The first function provided with @scheme[prop:equal+hash] is not
@ -257,33 +249,33 @@ types that are supposed to be equivalent.
@; ------------------------------------------------------------
@section{Structure Type Generativity}
Each time that a @scheme[define-struct] form is evaluated, it
Each time that a @scheme[struct] form is evaluated, it
generates a structure type that is distinct from all existing
structure types, even if some other structure type has the same name
and fields.
This generativity is useful for enforcing abstractions and
implementing programs such as interpreters, but beware of placing a
@scheme[define-struct] form in positions that are evaluated multiple
@scheme[struct] form in positions that are evaluated multiple
times.
@defexamples[
(define (add-bigger-fish lst)
(define-struct fish (size) #:transparent) (code:comment #,(t "new every time"))
(struct fish (size) #:transparent) (code:comment #,(t "new every time"))
(cond
[(null? lst) (list (make-fish 1))]
[else (cons (make-fish (* 2 (fish-size (car lst))))
[(null? lst) (list (fish 1))]
[else (cons (fish (* 2 (fish-size (car lst))))
lst)]))
(add-bigger-fish null)
(add-bigger-fish (add-bigger-fish null))
]
@defs+int[
[(define-struct fish (size) #:transparent)
[(struct fish (size) #:transparent)
(define (add-bigger-fish lst)
(cond
[(null? lst) (list (make-fish 1))]
[else (cons (make-fish (* 2 (fish-size (car lst))))
[(null? lst) (list (fish 1))]
[else (cons (fish (* 2 (fish-size (car lst))))
lst)]))]
(add-bigger-fish (add-bigger-fish null))
]
@ -322,16 +314,16 @@ the quotes above are optional:
]
When you use the @scheme[#:prefab] keyword with
@scheme[define-struct], instead of generating a new structure type,
@scheme[struct], instead of generating a new structure type,
you obtain bindings that work with the existing prefab structure type:
@interaction[
#:eval posn-eval
(define lunch '#s(sprout bean))
(define-struct sprout (kind) #:prefab)
(struct sprout (kind) #:prefab)
(sprout? lunch)
(sprout-kind lunch)
(make-sprout 'garlic)
(sprout 'garlic)
]
The field name @schemeidfont{kind} above does not matter for finding
@ -343,7 +335,7 @@ than the one with a single field:
@interaction[
#:eval posn-eval
(sprout? #s(sprout bean #f 17))
(code:line (define-struct sprout (kind yummy? count) #:prefab) (code:comment @#,t{redefine}))
(code:line (struct sprout (kind yummy? count) #:prefab) (code:comment @#,t{redefine}))
(sprout? #s(sprout bean #f 17))
(sprout? lunch)
]
@ -355,10 +347,10 @@ prefab structure types, and the printed form of the structure type's
name encodes all of the relevant details.
@interaction[
(define-struct building (rooms [location #:mutable]) #:prefab)
(define-struct (house building) ([occupied #:auto]) #:prefab
(struct building (rooms [location #:mutable]) #:prefab)
(struct house building ([occupied #:auto]) #:prefab
#:auto-value 'no)
(make-house 5 'factory)
(house 5 'factory)
]
Every @tech{prefab} structure type is @tech{transparent}---but even
@ -406,13 +398,13 @@ be serialized, however, if they are defined with
@; ------------------------------------------------------------
@section[#:tag "struct-options"]{More Structure Type Options}
The full syntax of @scheme[define-struct] supports many options, both
The full syntax of @scheme[struct] supports many options, both
at the structure-type level and at the level of individual fields:
@specform/subs[(define-struct id-maybe-super (field ...)
struct-option ...)
([id-maybe-super struct-id
(struct-id super-id)]
@specform/subs[(struct struct-id maybe-super (field ...)
struct-option ...)
([maybe-super code:blank
super-id]
[field field-id
[field-id field-option ...]])]
@ -426,8 +418,8 @@ A @scheme[_struct-option] always starts with a keyword:
that sets the value of the corresponding field in an instance of
the structure type.
@defexamples[(define-struct dot (x y) #:mutable)
(define d (make-dot 1 2))
@defexamples[(struct dot (x y) #:mutable)
(define d (dot 1 2))
(dot-x d)
(set-dot-x! d 10)
(dot-x d)]
@ -437,8 +429,8 @@ A @scheme[_struct-option] always starts with a keyword:
mutable.
@defexamples[
(define-struct person (name [age #:mutable]))
(define friend (make-person "Barney" 5))
(struct person (name [age #:mutable]))
(define friend (person "Barney" 5))
(set-person-age! friend 6)
(set-person-name! friend "Mary")]}
@ -464,10 +456,10 @@ A @scheme[_struct-option] always starts with a keyword:
functions are bound only if @scheme[#:mutator] is also specified.
@defexamples[
(define-struct posn (x y [z #:auto])
#:transparent
#:auto-value 0)
(make-posn 1 2)
(struct posn (x y [z #:auto])
#:transparent
#:auto-value 0)
(posn 1 2)
]}
@;-- FIXME:
@ -486,18 +478,18 @@ A @scheme[_struct-option] always starts with a keyword:
@defexamples[
#:eval posn-eval
(define-struct thing (name)
#:transparent
#:guard (lambda (name type-name)
(cond
[(string? name) name]
[(symbol? name) (symbol->string name)]
[else (error type-name
"bad name: ~e"
name)])))
(make-thing "apple")
(make-thing 'apple)
(make-thing 1/2)
(struct thing (name)
#:transparent
#:guard (lambda (name type-name)
(cond
[(string? name) name]
[(symbol? name) (symbol->string name)]
[else (error type-name
"bad name: ~e"
name)])))
(thing "apple")
(thing 'apple)
(thing 1/2)
]
The guard is called even when subtype instances are created. In that
@ -507,15 +499,15 @@ A @scheme[_struct-option] always starts with a keyword:
@defexamples[
#:eval posn-eval
(define-struct (person thing) (age)
#:transparent
#:guard (lambda (name age type-name)
(if (negative? age)
(error type-name "bad age: ~e" age)
(values name age))))
(make-person "John" 10)
(make-person "Mary" -1)
(make-person 10 10)]}
(struct person thing (age)
#:transparent
#:guard (lambda (name age type-name)
(if (negative? age)
(error type-name "bad age: ~e" age)
(values name age))))
(person "John" 10)
(person "Mary" -1)
(person 10 10)]}
@specspecsubform[(code:line #:property prop-expr val-expr)]{
Associates a @deftech{property} and value with the structure type.
@ -525,13 +517,13 @@ A @scheme[_struct-option] always starts with a keyword:
function.
@defexamples[
(define-struct greeter (name)
#:property prop:procedure
(lambda (self other)
(string-append
"Hi " other
", I'm " (greeter-name self))))
(define joe-greet (make-greeter "Joe"))
(struct greeter (name)
#:property prop:procedure
(lambda (self other)
(string-append
"Hi " other
", I'm " (greeter-name self))))
(define joe-greet (greeter "Joe"))
(greeter-name joe-greet)
(joe-greet "Mary")
(joe-greet "John")]}
@ -547,16 +539,16 @@ A @scheme[_struct-option] always starts with a keyword:
@defexamples[
#:eval posn-eval
(define (make-raven-constructor super-type)
(define-struct raven ()
#:super super-type
#:transparent
#:property prop:procedure (lambda (self)
'nevermore))
make-raven)
(let ([r ((make-raven-constructor struct:posn) 1 2)])
(define (raven-constructor super-type)
(struct raven ()
#:super super-type
#:transparent
#:property prop:procedure (lambda (self)
'nevermore))
raven)
(let ([r ((raven-constructor struct:posn) 1 2)])
(list r (r)))
(let ([r ((make-raven-constructor struct:thing) "apple")])
(let ([r ((raven-constructor struct:thing) "apple")])
(list r (r)))]}
@; ----------------------------------------

View File

@ -5,14 +5,14 @@
@(define def-eval (make-base-eval))
@title[#:tag "define"]{Definitions: @scheme[define]}
@title[#:tag "define"]{Definitions: @racket[define]}
A basic definition has the form
@specform[(define id expr)]{}
in which case @scheme[_id] is bound to the result of
@scheme[_expr].
in which case @racket[_id] is bound to the result of
@racket[_expr].
@defexamples[
#:eval def-eval
@ -23,14 +23,14 @@ salutation
@;------------------------------------------------------------------------
@section{Function Shorthand}
The @scheme[define] form also supports a shorthand for function
The @racket[define] form also supports a shorthand for function
definitions:
@specform[(define (id arg ...) body ...+)]{}
which is a shorthand for
@schemeblock[
@racketblock[
(define _id (lambda (_arg ...) _body ...+))
]
@ -50,7 +50,7 @@ which is a shorthand for
(greet "John" "Doe")
]
The function shorthand via @scheme[define] also supports a ``rest''
The function shorthand via @racket[define] also supports a ``rest''
argument (i.e., a final argument to collect extra arguments in a
list):
@ -58,7 +58,7 @@ list):
which is a shorthand
@schemeblock[
@racketblock[
(define _id (lambda (_arg ... . _rest-id) _body ...+))
]
@ -72,7 +72,7 @@ which is a shorthand
@;------------------------------------------------------------------------
@section{Curried Function Shorthand}
Consider the following @scheme[make-add-suffix] function that takes a
Consider the following @racket[make-add-suffix] function that takes a
string and returns another function that takes a string:
@def+int[
@ -82,7 +82,7 @@ string and returns another function that takes a string:
(lambda (s) (string-append s s2))))
]
Although it's not common, result of @scheme[make-add-suffix] could be
Although it's not common, result of @racket[make-add-suffix] could be
called directly, like this:
@interaction[
@ -90,21 +90,21 @@ called directly, like this:
((make-add-suffix "!") "hello")
]
In a sense, @scheme[make-add-suffix] is a function takes two
In a sense, @racket[make-add-suffix] is a 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
Using the function-shorthand form of @racket[define],
@racket[make-add-suffix] can be written equivalently as
@schemeblock[
@racketblock[
(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
@racket[(make-add-suffix "!")]. The @racket[define] form further
supports a shorthand for defining curried functions that reflects
nested function calls:
@ -122,26 +122,26 @@ nested function calls:
(louder "really")
]
The full syntax of the function shorthand for @scheme[define] is as follows:
The full syntax of the function shorthand for @racket[define] is as follows:
@specform/subs[(define (head args) body ...+)
([head id
(head args)]
[args (code:line arg ...)
(code:line arg ... @#,schemeparenfont{.} rest-id)])]{}
(code:line arg ... @#,racketparenfont{.} 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].
The expansion of this shorthand has one nested @racket[lambda] form
for each @racket[_head] in the definition, where the innermost
@racket[_head] corresponds to the outermost @racket[lambda].
@;------------------------------------------------------------------------
@section[#:tag "multiple-values"]{Multiple Values and @scheme[define-values]}
@section[#:tag "multiple-values"]{Multiple Values and @racket[define-values]}
A Scheme expression normally produces a single result, but some
A Racket expression normally produces a single result, but some
expressions can produce multiple results. For example,
@scheme[quotient] and @scheme[remainder] each produce a single value,
but @scheme[quotient/remainder] produces the same two values at once:
@racket[quotient] and @racket[remainder] each produce a single value,
but @racket[quotient/remainder] produces the same two values at once:
@interaction[
#:eval def-eval
@ -154,7 +154,7 @@ As shown above, the @tech{REPL} prints each result value on its own
line.
Multiple-valued functions can be implemented in terms of the
@scheme[values] function, which takes any number of values and
@racket[values] function, which takes any number of values and
returns them as the results:
@interaction[
@ -171,13 +171,13 @@ returns them as the results:
(split-name "Adam Smith")
]
The @scheme[define-values] form binds multiple identifiers at once to
The @racket[define-values] form binds multiple identifiers at once to
multiple results produced from a single expression:
@specform[(define-values (id ...) expr)]{}
The number of results produced by the @scheme[_expr] must match the
number of @scheme[_id]s.
The number of results produced by the @racket[_expr] must match the
number of @racket[_id]s.
@defexamples[
#:eval def-eval
@ -186,23 +186,23 @@ given
surname
]
A @scheme[define] form (that is not a function shorthand) is
equivalent to a @scheme[define-values] form with a single @scheme[_id].
A @racket[define] form (that is not a function shorthand) is
equivalent to a @racket[define-values] form with a single @racket[_id].
@refdetails["define"]{definitions}
@;------------------------------------------------------------------------
@section[#:tag "intdefs"]{Internal Definitions}
When the grammar for a syntactic form specifies @scheme[_body], then
When the grammar for a syntactic form specifies @racket[_body], then
the corresponding form can be either a definition or an expression.
A definition as a @scheme[_body] is an @defterm{internal definition}.
A definition as a @racket[_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
All internal definitions in a @racket[_body] sequence must appear
before any expression, and the last @racket[_body] must be an
expression.
For example, the syntax of @scheme[lambda] is
For example, the syntax of @racket[lambda] is
@specform[
(lambda gen-formals
@ -211,7 +211,7 @@ For example, the syntax of @scheme[lambda] is
so the following are valid instances of the grammar:
@schemeblock[
@racketblock[
(lambda (f) (code:comment @#,elem{no definitions})
(printf "running\n")
(f 0))
@ -236,7 +236,7 @@ so the following are valid instances of the grammar:
(call f n))
]
Internal definitions in a particular @scheme[_body] sequence are
Internal definitions in a particular @racket[_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,
@ -249,11 +249,11 @@ the result is a special value @|undefined-const|.
(weird)
]
A sequence of internal definitions using just @scheme[define] is
easily translated to an equivalent @scheme[letrec] form (as introduced
A sequence of internal definitions using just @racket[define] is
easily translated to an equivalent @racket[letrec] form (as introduced
in the next section). However, other definition forms can appear as a
@scheme[_body], including @scheme[define-values], @scheme[define-struct] (see
@secref["define-struct"]) or @scheme[define-syntax] (see
@racket[_body], including @racket[define-values], @racket[struct] (see
@secref["define-struct"]) or @racket[define-syntax] (see
@secref["macros"]).
@refdetails/gory["intdef-body"]{internal definitions}

View File

@ -5,7 +5,7 @@
@title[#:tag "scheme-forms" #:style 'toc]{Expressions and Definitions}
The @secref["to-scheme"] chapter introduced some of Scheme's syntactic
The @secref["to-scheme"] chapter introduced some of Racket's syntactic
forms: definitions, procedure applications, conditionals, and so
on. This section provides more details on those forms, plus a few
additional basic forms.
@ -17,32 +17,32 @@ additional basic forms.
This chapter (and the rest of the documentation) uses a slightly
different notation than the character-based grammars of the
@secref["to-scheme"] chapter. The grammar for a use of a syntactic
form @schemekeywordfont{something} is shown like this:
form @racketkeywordfont{something} is shown like this:
@specform[(#,(schemekeywordfont "something") [id ...+] an-expr ...)]
@specform[(#,(racketkeywordfont "something") [id ...+] an-expr ...)]
The italicized meta-variables in this specification, such as
@scheme[_id] and @scheme[_an-expr], use the syntax of Scheme
identifiers, so @scheme[_an-expr] is one meta-variable. A naming
@racket[_id] and @racket[_an-expr], use the syntax of Racket
identifiers, so @racket[_an-expr] is one meta-variable. A naming
convention implicitly defines the meaning of many meta-variables:
@itemize[
@item{A meta-variable that ends in @scheme[_id] stands for an
identifier, such as @schemeidfont{x} or
@schemeidfont{my-favorite-martian}.}
@item{A meta-variable that ends in @racket[_id] stands for an
identifier, such as @racketidfont{x} or
@racketidfont{my-favorite-martian}.}
@item{A meta-identifier that ends in @scheme[_keyword] stands
for a keyword, such as @scheme[#:tag].}
@item{A meta-identifier that ends in @racket[_keyword] stands
for a keyword, such as @racket[#:tag].}
@item{A meta-identifier that ends with @scheme[_expr] stands for any
@item{A meta-identifier that ends with @racket[_expr] stands for any
sub-form, and it will be parsed as an expression.}
@item{A meta-identifier that ends with @scheme[_body] stands for any
@item{A meta-identifier that ends with @racket[_body] stands for any
sub-form; it will be parsed as either a local definition or an
expression. A @scheme[_body] can parse as a definition only if
expression. A @racket[_body] can parse as a definition only if
it is not preceded by any expression, and the last
@scheme[_body] must be an expression; see also @secref["intdefs"].}
@racket[_body] must be an expression; see also @secref["intdefs"].}
]
@ -51,18 +51,18 @@ forms, where square brackets are normally used (by convention). That
is, square brackets @italic{do not} mean optional parts of the
syntactic form.
A @schememetafont{...} indicates zero or more repetitions of the
preceding form, and @schememetafont{...+} indicates one or more
A @racketmetafont{...} indicates zero or more repetitions of the
preceding form, and @racketmetafont{...+} indicates one or more
repetitions of the preceding datum. Otherwise, non-italicized
identifiers stand for themselves.
Based on the above grammar, then, here are a few conforming uses of
@schemekeywordfont{something}:
@racketkeywordfont{something}:
@schemeblock[
(#,(schemekeywordfont "something") [x])
(#,(schemekeywordfont "something") [x] (+ 1 2))
(#,(schemekeywordfont "something") [x my-favorite-martian x] (+ 1 2) #f)
@racketblock[
(#,(racketkeywordfont "something") [x])
(#,(racketkeywordfont "something") [x] (+ 1 2))
(#,(racketkeywordfont "something") [x my-favorite-martian x] (+ 1 2) #f)
]
Some syntactic-form specifications refer to meta-variables that are
@ -70,12 +70,12 @@ not implicitly defined and not previously defined. Such meta-variables
are defined after the main form, using a BNF-like format for
alternatives:
@specform/subs[(#,(schemekeywordfont "something-else") [thing ...+] an-expr ...)
@specform/subs[(#,(racketkeywordfont "something-else") [thing ...+] an-expr ...)
([thing thing-id
thing-keyword])]
The above example says that, within a @schemekeywordfont{something-else}
form, a @scheme[_thing] is either an identifier or a keyword.
The above example says that, within a @racketkeywordfont{something-else}
form, a @racket[_thing] is either an identifier or a keyword.
@;------------------------------------------------------------------------

View File

@ -1,12 +1,12 @@
(module guide-utils scheme/base
(module guide-utils racket/base
(require scribble/manual
scribble/struct
scribble/decode
scribble/eval
"../icons.ss")
(require (for-label scheme/base))
(provide (for-label (all-from-out scheme/base)))
(require (for-label racket/base))
(provide (for-label (all-from-out racket/base)))
(provide Quick MzScheme HtDP
tool

View File

@ -2,19 +2,18 @@
@(require scribble/eval
"guide-utils.ss")
@title{@bold{Guide}: PLT Scheme}
@title{@bold{Guide}: Racket}
@author["Matthew Flatt" "Robert Bruce Findler" "PLT"]
This guide is intended for programmers who are new to Scheme, new to PLT
Scheme, or new to some part of PLT Scheme. It assumes
programming experience, so if you are new to programming, consider
instead reading @|HtDP|. If you want a brief introduction to PLT
Scheme, start with @|Quick|.
This guide is intended for programmers who are new to Racket or new to
some part of Racket. It assumes programming experience, so if you are
new to programming, consider instead reading @|HtDP|. If you want an
especially quick introduction to Racket, start with @|Quick|.
@seclink["to-scheme"]{Chapter 2} provides a brief introduction to
Scheme. From @seclink["datatypes"]{Chapter 3} on, this guide dives
into details---covering much of the PLT Scheme toolbox, but leaving
Racket. From @seclink["datatypes"]{Chapter 3} on, this guide dives
into details---covering much of the Racket toolbox, but leaving
precise details to @|MzScheme| and other reference manuals.
@table-of-contents[]

View File

@ -22,7 +22,7 @@ way that an identifier can be quoted to produce a symbol, a keyword
can be quoted to produce a value. The same term ``keyword'' is used in
both cases, but we sometimes use @defterm{keyword value} to refer more
specifically to the result of a quote-keyword expression or of
@scheme[string->keyword]. An unquoted keyword is not an expression,
@racket[string->keyword]. An unquoted keyword is not an expression,
just as an unquoted identifier does not produce a symbol:
@examples[
@ -37,12 +37,12 @@ run-time flags and enumerations, use symbols instead of keywords. The
example below illustrates the distinct roles of keywords and symbols.
@examples[
(code:line (define dir (find-system-path 'temp-dir)) (code:comment @#,t{not @scheme['#:temp-dir]}))
(code:line (define dir (find-system-path 'temp-dir)) (code:comment @#,t{not @racket['#:temp-dir]}))
(with-output-to-file (build-path dir "stuff.txt")
(lambda () (printf "example\n"))
(code:comment @#,t{optional @scheme[#:mode] argument can be @scheme['text] or @scheme['binary]})
(code:comment @#,t{optional @racket[#:mode] argument can be @racket['text] or @racket['binary]})
#:mode 'text
(code:comment @#,t{optional @scheme[#:exists] argument can be @scheme['replace], @scheme['truncate], ...})
(code:comment @#,t{optional @racket[#:exists] argument can be @racket['replace], @racket['truncate], ...})
#:exists 'replace)
]

View File

@ -5,17 +5,17 @@
@(define greet-eval (make-base-eval))
@title[#:tag "lambda"]{Functions@aux-elem{ (Procedures)}: @scheme[lambda]}
@title[#:tag "lambda"]{Functions@aux-elem{ (Procedures)}: @racket[lambda]}
A @scheme[lambda] expression creates a function. In the simplest
case, a @scheme[lambda] expression has the form
A @racket[lambda] expression creates a function. In the simplest
case, a @racket[lambda] expression has the form
@specform[
(lambda (arg-id ...)
body ...+)
]
A @scheme[lambda] form with @math{n} @scheme[_arg-id]s accepts
A @racket[lambda] form with @math{n} @racket[_arg-id]s accepts
@math{n} arguments:
@interaction[
@ -30,17 +30,17 @@ A @scheme[lambda] form with @math{n} @scheme[_arg-id]s accepts
@;------------------------------------------------------------------------
@section{Declaring a Rest Argument}
A @scheme[lambda] expression can also have the form
A @racket[lambda] expression can also have the form
@specform[
(lambda rest-id
body ...+)
]
That is, a @scheme[lambda] expression can have a single
@scheme[_rest-id] that is not surrounded by parentheses. The resulting
That is, a @racket[lambda] expression can have a single
@racket[_rest-id] that is not surrounded by parentheses. The resulting
function accepts any number of arguments, and the arguments are put
into a list bound to @scheme[_rest-id].
into a list bound to @racket[_rest-id].
@examples[
((lambda x x)
@ -50,10 +50,10 @@ into a list bound to @scheme[_rest-id].
1 2 3)
]
Functions with a @scheme[_rest-id] often use @scheme[apply] to call
Functions with a @racket[_rest-id] often use @racket[apply] to call
another function that accepts any number of arguments.
@guideother{@secref["apply"] describes @scheme[apply].}
@guideother{@secref["apply"] describes @racket[apply].}
@defexamples[
(define max-mag
@ -64,8 +64,8 @@ another function that accepts any number of arguments.
(max-mag 1 -2 0)
]
The @scheme[lambda] form also supports required arguments combined
with a @scheme[_rest-id]:
The @racket[lambda] form also supports required arguments combined
with a @racket[_rest-id]:
@specform[
(lambda (arg-id ...+ . rest-id)
@ -73,7 +73,7 @@ with a @scheme[_rest-id]:
]
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
arguments as @racket[_arg-id]s, and also accepts any number of
additional arguments.
@defexamples[
@ -85,14 +85,14 @@ additional arguments.
(max-mag)
]
A @scheme[_rest-id] variable is sometimes called a @defterm{rest
A @racket[_rest-id] variable is sometimes called a @defterm{rest
argument}, because it accepts the ``rest'' of the function arguments.
@;------------------------------------------------------------------------
@section{Declaring Optional Arguments}
Instead of just an identifier, an argument (other than a rest
argument) in a @scheme[lambda] form can be specified with an
argument) in a @racket[lambda] form can be specified with an
identifier and a default value:
@specform/subs[
@ -105,11 +105,11 @@ identifier and a default value:
[arg-id default-expr]])
]{}
A argument of the form @scheme[[arg-id default-expr]] is
A argument of the form @racket[[arg-id default-expr]] is
optional. When the argument is not supplied in an application,
@scheme[_default-expr] produces the default value. The
@scheme[_default-expr] can refer to any preceding @scheme[_arg-id],
and every following @scheme[_arg-id] must have a default as well.
@racket[_default-expr] produces the default value. The
@racket[_default-expr] can refer to any preceding @racket[_arg-id],
and every following @racket[_arg-id] must have a default as well.
@defexamples[
(define greet
@ -133,7 +133,7 @@ and every following @scheme[_arg-id] must have a default as well.
@section[#:tag "lambda-keywords"]{Declaring Keyword Arguments}
A @scheme[lambda] form can declare an argument to be passed by
A @racket[lambda] form can declare an argument to be passed by
keyword, instead of position. Keyword arguments can be mixed with
by-position arguments, and default-value expressions can be supplied
for either kind of argument:
@ -153,8 +153,8 @@ calls with keywords.}
(code:line arg-keyword [arg-id default-expr])])
]{}
An argument specified as @scheme[(code:line _arg-keyword _arg-id)] is
supplied by an application using the same @scheme[_arg-keyword]. The
An argument specified as @racket[(code:line _arg-keyword _arg-id)] is
supplied by an application using the same @racket[_arg-keyword]. The
position of the keyword--identifier pair in the argument list does not
matter for matching with arguments in an application, because it will
be matched to an argument value by keyword instead of by position.
@ -168,7 +168,7 @@ be matched to an argument value by keyword instead of by position.
(greet #:last "Doe" "John")
]
An @scheme[(code:line _arg-keyword [_arg-id _default-expr])] argument
An @racket[(code:line _arg-keyword [_arg-id _default-expr])] argument
specifies a keyword-based argument with a default value.
@defexamples[
@ -183,16 +183,16 @@ specifies a keyword-based argument with a default value.
(greet "Karl" #:last "Marx" #:hi "Guten Tag")
]
The @scheme[lambda] form does not directly support the creation
The @racket[lambda] form does not directly support the creation
of a function that accepts ``rest'' keywords. To construct a
function that accepts all keyword arguments, use
@scheme[make-keyword-procedure]. The function supplied to
@scheme[make-keyword-procedure] receives keyword arguments
@racket[make-keyword-procedure]. The function supplied to
@racket[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
remaining by-position arguments.
@guideother{@secref["apply"] introduces @scheme[keyword-apply].}
@guideother{@secref["apply"] introduces @racket[keyword-apply].}
@defexamples[
#:eval greet-eval
@ -207,9 +207,9 @@ remaining by-position arguments.
@refdetails["lambda"]{function expressions}
@;------------------------------------------------------------------------
@section{Arity-Sensitive Functions: @scheme[case-lambda]}
@section{Arity-Sensitive Functions: @racket[case-lambda]}
The @scheme[case-lambda] form creates a function that can have
The @racket[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
@ -222,9 +222,9 @@ that are supplied. A case-lambda expression has the form
(arg-id ...+ . rest-id)])
]
where each @scheme[[_formals _body ...+]] is analogous to @scheme[(lambda
where each @racket[[_formals _body ...+]] is analogous to @racket[(lambda
_formals _body ...+)]. Applying a function produced by
@scheme[case-lambda] is like applying a @scheme[lambda] for the first
@racket[case-lambda] is like applying a @racket[lambda] for the first
case that matches the number of given arguments.
@defexamples[
@ -238,7 +238,7 @@ case that matches the number of given arguments.
(greet)
]
A @scheme[case-lambda] function cannot directly support optional or
A @racket[case-lambda] function cannot directly support optional or
keyword arguments.
@; ----------------------------------------------------------------------

View File

@ -5,24 +5,24 @@
@title[#:tag "let"]{Local Binding}
Although internal @scheme[define]s can be used for local binding,
Scheme provides three forms that give the programmer more
control over bindings: @scheme[let], @scheme[let*], and
@scheme[letrec].
Although internal @racket[define]s can be used for local binding,
Racket provides three forms that give the programmer more
control over bindings: @racket[let], @racket[let*], and
@racket[letrec].
@;------------------------------------------------------------------------
@section{Parallel Binding: @scheme[let]}
@section{Parallel Binding: @racket[let]}
@refalso["let"]{@scheme[let]}
@refalso["let"]{@racket[let]}
A @scheme[let] form binds a set of identifiers, each to the result of
some expression, for use in the @scheme[let] body:
A @racket[let] form binds a set of identifiers, each to the result of
some expression, for use in the @racket[let] body:
@specform[(let ([id expr] ...) body ...+)]{}
The @scheme[_id]s are bound ``in parallel.'' That is, no @scheme[_id]
is bound in the right-hand side @scheme[_expr] for any @scheme[_id],
but all are available in the @scheme[_body]. The @scheme[_id]s must be
The @racket[_id]s are bound ``in parallel.'' That is, no @racket[_id]
is bound in the right-hand side @racket[_expr] for any @racket[_id],
but all are available in the @racket[_body]. The @racket[_id]s must be
different from each other.
@examples[
@ -37,7 +37,7 @@ different from each other.
me)
]
The fact that an @scheme[_id]'s @scheme[_expr] does not see its own
The fact that an @racket[_id]'s @racket[_expr] does not see its own
binding is often useful for wrappers that must refer back to the old
value:
@ -45,12 +45,12 @@ value:
(let ([+ (lambda (x y)
(if (string? x)
(string-append x y)
(+ x y)))]) (code:comment @#,t{use original @scheme[+]})
(+ x y)))]) (code:comment @#,t{use original @racket[+]})
(list (+ 1 2)
(+ "see" "saw")))
]
Occasionally, the parallel nature of @scheme[let] bindings is
Occasionally, the parallel nature of @racket[let] bindings is
convenient for swapping or rearranging a set of bindings:
@interaction[
@ -61,23 +61,23 @@ convenient for swapping or rearranging a set of bindings:
(list me you)))
]
The characterization of @scheme[let] bindings as ``parallel'' is not
meant to imply concurrent evaluation. The @scheme[_expr]s are
The characterization of @racket[let] bindings as ``parallel'' is not
meant to imply concurrent evaluation. The @racket[_expr]s are
evaluated in order, even though the bindings are delayed until all
@scheme[_expr]s are evaluated.
@racket[_expr]s are evaluated.
@;------------------------------------------------------------------------
@section{Sequential Binding: @scheme[let*]}
@section{Sequential Binding: @racket[let*]}
@refalso["let"]{@scheme[let*]}
@refalso["let"]{@racket[let*]}
The syntax of @scheme[let*] is the same as @scheme[let]:
The syntax of @racket[let*] is the same as @racket[let]:
@specform[(let* ([id expr] ...) body ...+)]{}
The difference is that each @scheme[_id] is available for use in later
@scheme[_expr]s, as well as in the @scheme[_body]. Furthermore, the
@scheme[_id]s need not be distinct, and the most recent binding is the
The difference is that each @racket[_id] is available for use in later
@racket[_expr]s, as well as in the @racket[_body]. Furthermore, the
@racket[_id]s need not be distinct, and the most recent binding is the
visible one.
@examples[
@ -91,8 +91,8 @@ visible one.
name)
]
In other words, a @scheme[let*] form is equivalent to nested
@scheme[let] forms, each with a single binding:
In other words, a @racket[let*] form is equivalent to nested
@racket[let] forms, each with a single binding:
@interaction[
(let ([name (list "Borroughs")])
@ -102,22 +102,22 @@ In other words, a @scheme[let*] form is equivalent to nested
]
@;------------------------------------------------------------------------
@section{Recursive Binding: @scheme[letrec]}
@section{Recursive Binding: @racket[letrec]}
@refalso["let"]{@scheme[letrec]}
@refalso["let"]{@racket[letrec]}
The syntax of @scheme[letrec] is also the same as @scheme[let]:
The syntax of @racket[letrec] is also the same as @racket[let]:
@specform[(letrec ([id expr] ...) body ...+)]{}
While @scheme[let] makes its bindings available only in the
@scheme[_body]s, and @scheme[let*] makes its bindings available to any
later binding @scheme[_expr], @scheme[letrec] makes its bindings
available to all other @scheme[_expr]s---even earlier ones. In other
words, @scheme[letrec] bindings are recursive.
While @racket[let] makes its bindings available only in the
@racket[_body]s, and @racket[let*] makes its bindings available to any
later binding @racket[_expr], @racket[letrec] makes its bindings
available to all other @racket[_expr]s---even earlier ones. In other
words, @racket[letrec] bindings are recursive.
The @scheme[_expr]s in a @scheme[letrec] form are most often
@scheme[lambda] forms for recursive and mutually recursive functions:
The @racket[_expr]s in a @racket[letrec] form are most often
@racket[lambda] forms for recursive and mutually recursive functions:
@interaction[
(letrec ([swing
@ -145,11 +145,11 @@ The @scheme[_expr]s in a @scheme[letrec] form are most often
(tarzan-in-tree? "tmp" (find-system-path 'temp-dir)))
]
While the @scheme[_expr]s of a @scheme[letrec] form are typically
@scheme[lambda] expressions, they can be any expression. The
While the @racket[_expr]s of a @racket[letrec] form are typically
@racket[lambda] expressions, they can be any expression. The
expressions are evaluated in order, and after each value is obtained,
it is immediately associated with its corresponding @scheme[_id]. If
an @scheme[_id] is referenced before its value is ready, the result is
it is immediately associated with its corresponding @racket[_id]. If
an @racket[_id] is referenced before its value is ready, the result is
@|undefined-const|, as just as for internal definitions.
@interaction[
@ -161,14 +161,14 @@ an @scheme[_id] is referenced before its value is ready, the result is
@include-section["named-let.scrbl"]
@; ----------------------------------------
@section{Multiple Values: @scheme[let-values], @scheme[let*-values], @scheme[letrec-values]}
@section{Multiple Values: @racket[let-values], @racket[let*-values], @racket[letrec-values]}
@refalso["let"]{multiple-value binding forms}
In the same way that @scheme[define-values] binds multiple
In the same way that @racket[define-values] binds multiple
results in a definition (see @secref["multiple-values"]),
@scheme[let-values], @scheme[let*-values], and
@scheme[letrec-values] bind multiple results locally.
@racket[let-values], @racket[let*-values], and
@racket[letrec-values] bind multiple results locally.
@specform[(let-values ([(id ...) expr] ...)
body ...+)]
@ -177,13 +177,13 @@ results in a definition (see @secref["multiple-values"]),
@specform[(letrec-values ([(id ...) expr] ...)
body ...+)]
Each @scheme[_expr] must produce as many values as corresponding
@scheme[_id]s. The binding rules are the same for the forms
without @schemekeywordfont{-values} forms: the @scheme[_id]s of
@scheme[let-values] are bound only in the @scheme[_body]s, the
@scheme[_id]s of @scheme[let*-values]s are bound in
@scheme[_expr]s of later clauses, and the @scheme[_id]s of
@scheme[letrec-value]s are bound for all @scheme[_expr]s.
Each @racket[_expr] must produce as many values as corresponding
@racket[_id]s. The binding rules are the same for the forms
without @racketkeywordfont{-values} forms: the @racket[_id]s of
@racket[let-values] are bound only in the @racket[_body]s, the
@racket[_id]s of @racket[let*-values]s are bound in
@racket[_expr]s of later clauses, and the @racket[_id]s of
@racket[letrec-value]s are bound for all @racket[_expr]s.
@examples[
(let-values ([(q r) (quotient/remainder 14 3)])

View File

@ -2,35 +2,35 @@
@(require scribble/manual
scribble/eval
scribble/bnf
scheme/list
(for-label scheme/list)
racket/list
(for-label racket/list)
"guide-utils.ss")
@(define step @elem{=})
@(define list-eval (make-base-eval))
@(interaction-eval #:eval list-eval (require scheme/list))
@(interaction-eval #:eval list-eval (require racket/list))
@title{Lists, Iteration, and Recursion}
Scheme is a dialect of the language Lisp, whose name originally stood
Racket 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] function takes any number of values and returns
The @racket[list] function takes any number of values and returns
a list containing the values:
@interaction[(list "red" "green" "blue")
(list 1 2 3 4 5)]
As you can see, a list result prints in the @tech{REPL} as a pair of
parentheses wrapped around the printed form of the list
elements. There's an opportunity for confusion here, because
parentheses are used for both expressions, such as @scheme[(list "red"
"green" "blue")], and printed results, such as @schemeresult[("red"
"green" "blue")]. Remember that, in the documentation and in
DrScheme, parentheses for results are printed in blue, whereas
parentheses for expressions are brown.
As you can see, a list result prints in the @tech{REPL} as a backquote
@litchar{`} and then a pair of parentheses wrapped around the printed
form of the list elements. There's an opportunity for confusion here,
because parentheses are used for both expressions, such as
@racket[(list "red" "green" "blue")], and printed results, such as
@racketresult['("red" "green" "blue")]. In addition to the backquote,
parentheses for results are printed in blue in the documentation and
in DrRacket, whereas parentheses for expressions are brown.
Many predefined functions operate on lists. Here are a few examples:
@ -46,15 +46,15 @@ Many predefined functions operate on lists. Here are a few examples:
@;------------------------------------------------------------------------
@section{Predefined List Loops}
In addition to simple operations like @scheme[append], Scheme includes
In addition to simple operations like @racket[append], Racket includes
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
functions play a role similar to @racket[for] in Java, Racket, and other
languages. The body of a Racket iteration is packaged into a function
to be applied to each element, so the @racket[lambda] form becomes
particularly handy in combination with iteration functions.
Different list-iteration functions combine iteration results in
different ways. The @scheme[map] function uses the per-element
different ways. The @racket[map] function uses the per-element
results to create a new list:
@interaction[
@ -64,8 +64,8 @@ results to create a new list:
(list "peanuts" "popcorn" "crackerjack"))
]
The @scheme[andmap] and @scheme[ormap] functions combine the results
by @scheme[and]ing or @scheme[or]ing:
The @racket[andmap] and @racket[ormap] functions combine the results
by @racket[and]ing or @racket[or]ing:
@interaction[
(andmap string? (list "a" "b" "c"))
@ -73,15 +73,15 @@ by @scheme[and]ing or @scheme[or]ing:
(ormap number? (list "a" "b" 6))
]
The @scheme[filter] function keeps elements for which the body result
is true, and discards elements for which it is @scheme[#f]:
The @racket[filter] function keeps elements for which the body result
is true, and discards elements for which it is @racket[#f]:
@interaction[
(filter string? (list "a" "b" 6))
(filter positive? (list 1 -2 6 7 0))
]
The @scheme[map], @scheme[andmap], @scheme[ormap], and @scheme[filter]
The @racket[map], @racket[andmap], @racket[ormap], and @racket[filter]
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:
@ -92,7 +92,7 @@ must accept one argument for each list:
(list 6 3 7))
]
The @scheme[foldl] function generalizes some iteration functions. It
The @racket[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
@ -105,31 +105,31 @@ provided before the lists:
'(1 2 3))
]
Despite its generality, @scheme[foldl] is not as popular as the other
functions. One reason is that @scheme[map], @scheme[ormap],
@scheme[andmap], and @scheme[filter] cover the most common kinds of
Despite its generality, @racket[foldl] is not as popular as the other
functions. One reason is that @racket[map], @racket[ormap],
@racket[andmap], and @racket[filter] cover the most common kinds of
list loops.
Scheme provides a general @defterm{list comprehension} form
@scheme[for/list], which builds a list by iterating through
Racket provides a general @defterm{list comprehension} form
@racket[for/list], which builds a list by iterating through
@defterm{sequences}. List comprehensions and related iteration forms
are described in see @secref["for"].
@;------------------------------------------------------------------------
@section{List Iteration from Scratch}
Although @scheme[map] and other iteration functions predefined, they
Although @racket[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.
Since a Scheme list is a linked list, the two core operations on a
Since a Racket list is a linked list, the two core operations on a
non-empty list are
@itemize[
@item{@scheme[first]: get the first thing in the list; and}
@item{@racket[first]: get the first thing in the list; and}
@item{@scheme[rest]: get the rest of the list.}
@item{@racket[rest]: get the rest of the list.}
]
@ -140,9 +140,9 @@ 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] function, which is short for
of the list---use the @racket[cons] function, which is short for
``construct.'' To get an empty list to start with, use the
@scheme[empty] constant:
@racket[empty] constant:
@interaction[
#:eval list-eval
@ -152,9 +152,9 @@ 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?] function detects empty lists,
and @scheme[cons?] detects non-empty lists:
non-empty lists, because @racket[first] and @racket[rest] work only on
non-empty lists. The @racket[empty?] function detects empty lists,
and @racket[cons?] detects non-empty lists:
@interaction[
#:eval list-eval
@ -165,7 +165,7 @@ and @scheme[cons?] detects non-empty lists:
]
With these pieces, you can write your own versions of the
@scheme[length] function, @scheme[map] function, and more.
@racket[length] function, @racket[map] function, and more.
@defexamples[
#:eval list-eval
@ -193,11 +193,11 @@ of recursive calls instead of a looping construct, then read on.
@;------------------------------------------------------------------------
@section[#:tag "tail-recursion"]{Tail Recursion}
Both the @scheme[my-length] and @scheme[my-map] functions run in
Both the @racket[my-length] and @racket[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:
imagining how @racket[(my-length (list "a" "b" "c"))] must evaluate:
@schemeblock[
@racketblock[
#||# (my-length (list "a" "b" "c"))
#,step (+ 1 (my-length (list "b" "c")))
#,step (+ 1 (+ 1 (my-length (list "c"))))
@ -209,29 +209,29 @@ imagining how @scheme[(my-length (list "a" "b" "c"))] must evaluate:
]
For a list with @math{n} elements, evaluation will stack up @math{n}
@scheme[(+ 1 ...)] additions, and then finally add them up when the
@racket[(+ 1 ...)] additions, and then finally add them up when the
list is exhausted.
You can avoid piling up additions by adding along the way. To
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 function @scheme[iter] that accumulates the length in an
argument @scheme[len]:
local function @racket[iter] that accumulates the length in an
argument @racket[len]:
@schemeblock[
@racketblock[
(define (my-length lst)
(code:comment @#,t{local function @scheme[iter]:})
(code:comment @#,t{local function @racket[iter]:})
(define (iter lst len)
(cond
[(empty? lst) len]
[else (iter (rest lst) (+ len 1))]))
(code:comment @#,t{body of @scheme[my-length] calls @scheme[iter]:})
(code:comment @#,t{body of @racket[my-length] calls @racket[iter]:})
(iter lst 0))
]
Now evaluation looks like this:
@schemeblock[
@racketblock[
#||# (my-length (list "a" "b" "c"))
#,step (iter (list "a" "b" "c") 0)
#,step (iter (list "b" "c") 1)
@ -240,21 +240,21 @@ Now evaluation looks like this:
3
]
The revised @scheme[my-length] runs in constant space, just as the
The revised @racket[my-length] runs in constant space, just as the
evaluation steps above suggest. That is, when the result of a
function call, like @scheme[(iter (list "b" "c") 1)], is exactly the
result of some other function call, like @scheme[(iter (list "c")
function call, like @racket[(iter (list "b" "c") 1)], is exactly the
result of some other function call, like @racket[(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.
This evaluation behavior is sometimes called @idefterm{tail-call
optimization}, but it's not merely an ``optimization'' in Scheme; it's
optimization}, but it's not merely an ``optimization'' in Racket; it's
a guarantee about the way the code will run. More precisely, an
expression in @idefterm{tail position} with respect to another
expression in @deftech{tail position} with respect to another
expression does not take extra computation space over the other
expression.
In the case of @scheme[my-map], @math{O(n)} space complexity is
In the case of @racket[my-map], @math{O(n)} space complexity is
reasonable, since it has to generate a result of size
@math{O(n)}. Nevertheless, you can reduce the constant factor by
accumulating the result list. The only catch is that the accumulated
@ -263,7 +263,7 @@ list will be backwards, so you'll have to reverse it at the very end:
@margin-note{Attempting to reduce a constant factor like this is
usually not worthwhile, as discussed below.}
@schemeblock[
@racketblock[
(define (my-map f lst)
(define (iter lst backward-result)
(cond
@ -276,40 +276,40 @@ usually not worthwhile, as discussed below.}
It turns out that if you write
@schemeblock[
@racketblock[
(define (my-map f lst)
(for/list ([i lst])
(f i)))
]
then the @scheme[for/list] form in the function both is expanded to
essentially the same code as the @scheme[iter] local definition and
then the @racket[for/list] form in the function both is expanded to
essentially the same code as the @racket[iter] local definition and
use. The difference is merely syntactic convenience.
@;------------------------------------------------------------------------
@section{Recursion versus Iteration}
The @scheme[my-length] and @scheme[my-map] examples demonstrate that
The @racket[my-length] and @racket[my-map] examples demonstrate that
iteration is just a special case of recursion. In many languages, it's
important to try to fit as many computations as possible into
iteration form. Otherwise, performance will be bad, and moderately
large inputs can lead to stack overflow. Similarly, in Scheme, it is
large inputs can lead to stack overflow. Similarly, in Racket, it is
sometimes important to make sure that tail recursion is used to avoid
@math{O(n)} space consumption when the computation is easily performed
in constant space.
At the same time, recursion does not lead to particularly bad
performance in Scheme, and there is no such thing as stack overflow;
performance in Racket, and there is no such thing as stack overflow;
you can run out of memory if a computation involves too much context,
but exhausting memory typically requires orders of magnitude deeper
recursion than would trigger a stack overflow in other
languages. These considerations, combined with the fact that
tail-recursive programs automatically run the same as a loop, lead
Scheme programmers to embrace recursive forms rather than avoid them.
Racket 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 function can be written as a loop that
remembers the previous element for each iteration, a Scheme programmer
remembers the previous element for each iteration, a Racket programmer
would more likely just write the following:
@def+int[
@ -330,12 +330,12 @@ 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)}---and @racket[remove-dups] will also use much less than
@math{O(n)} space! The reason is that when the function discards
duplicates, it returns the result of a @scheme[remove-dups] call
duplicates, it returns the result of a @racket[remove-dups] call
directly, so the tail-call ``optimization'' kicks in:
@schemeblock[
@racketblock[
#||# (remove-dups (list "a" "b" "b" "b" "b" "b"))
#,step (cons "a" (remove-dups (list "b" "b" "b" "b" "b")))
#,step (cons "a" (remove-dups (list "b" "b" "b" "b")))

View File

@ -6,17 +6,17 @@
@title[#:tag "module-basics"]{Module Basics}
The space of module names is distinct from the space of normal Scheme
The space of module names is distinct from the space of normal Racket
definitions. Indeed, since modules typically reside in files, the
space of module names is explicitly tied to the filesystem at run
time. For example, if the file @filepath{/home/molly/cake.ss} contains
time. For example, if the file @filepath{/home/molly/cake.rkt} contains
@schememod[
scheme
@racketmod[
racket
(provide print-cake)
(code:comment @#,t{draws a cake with @scheme[n] candles})
(code:comment @#,t{draws a cake with @racket[n] candles})
(define (print-cake n)
(printf " ~a \n" (make-string n #\.))
(printf " .-~a-.\n" (make-string n #\|))
@ -25,40 +25,40 @@ scheme
]
then it can be used as the source of a module whose full name is based
on the path @filepath{/home/molly/cake.ss}. The @scheme[provide] line
exports the definition @scheme[print-cake] so that it can be used
on the path @filepath{/home/molly/cake.rkt}. The @racket[provide] line
exports the definition @racket[print-cake] so that it can be used
outside the module.
Instead of using its full path, a module is more likely to be
referenced by a relative path. For example, a file
@filepath{/home/molly/random-cake.ss} could use the @filepath{cake.ss} module
@filepath{/home/molly/random-cake.rkt} could use the @filepath{cake.rkt} module
like this:
@schememod[
scheme
@racketmod[
racket
(require "cake.ss")
(require "cake.rkt")
(print-cake (random 30))
]
The relative reference @scheme["cake.ss"] in the import
@scheme[(require "cake.ss")] works because the @filepath{cake.ss} module
source is in the same directory as the @filepath{random-cake.ss}
The relative reference @racket["cake.rkt"] in the import
@racket[(require "cake.rkt")] works because the @filepath{cake.rkt} module
source is in the same directory as the @filepath{random-cake.rkt}
file. (Unix-style relative paths are used for relative module
references on all platforms, much like relative URLs.)
Library modules that are distributed with PLT Scheme are usually
Library modules that are distributed with Racket are usually
referenced through an unquoted, suffixless path. The path is relative
to the library installation directory, which contains directories for
individual library @deftech{collections}. The module below refers to
the @filepath{date.ss} library that is part of the @filepath{scheme}
the @filepath{date.rkt} library that is part of the @filepath{racket}
@tech{collection}.
@schememod[
scheme
@racketmod[
racket
(require scheme/date)
(require racket/date)
(printf "Today is ~s\n"
(date->string (seconds->date (current-seconds))))
@ -71,8 +71,8 @@ collection directories can be specified in configuration files or
through the @envvar{PLTCOLLECTS} search path. Try running the
following program to find out where your collections are:
@schememod[
scheme
@racketmod[
racket
(require setup/dirs)

View File

@ -6,92 +6,104 @@
@title[#:tag "module-paths"]{Module Paths}
A @deftech{module path} is a reference to a module, as used with
@scheme[require] or as the @scheme[_initial-module-path] in a
@scheme[module] form. It can be any of several forms:
@racket[require] or as the @racket[_initial-module-path] in a
@racket[module] form. It can be any of several forms:
@; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@specsubform[#:literals (quote) (#,(scheme quote) id)]{
@specsubform[#:literals (quote) (#,(racket quote) id)]{
A @tech{module path} that is a quoted identifier refers to a non-file
@scheme[module] declaration using the identifier. This form of module
@racket[module] declaration using the identifier. This form of module
reference makes the most sense in a @tech{REPL}.
@examples[
(module m scheme
(module m racket
(provide color)
(define color "blue"))
(module n scheme
(module n racket
(require 'm)
(printf "my favorite color is ~a\n" color))
(require 'n)
]}
@; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@specsubform[id]{
A @tech{module path} that is an unquoted identifier refers to an
installed library. The @scheme[id] is constrained to contain only
ASCII letters, ASCII numbers, @litchar{+}, @litchar{-}, @litchar{_},
and @litchar{/}, where @litchar{/} separates path elements within the
identifier. The elements refer to @tech{collection}s and
sub-@tech{collections}, instead of directories and sub-directories.
An example of this form is @scheme[scheme/date]. It refers to the
module whose source is the @filepath{date.ss} file in the
@filepath{scheme} collection, which is installed as part of PLT
Scheme. The @filepath{.ss} suffix is added automatically.
Another example of this form is @scheme[scheme], which is commonly
used at the initial import. The path @scheme[scheme] is shorthand for
@scheme[scheme/main]; when an @scheme[id] has no @litchar{/}, then
@scheme[/main] is automatically added to the end. Thus,
@scheme[scheme] or @scheme[scheme/main] refers to the module whose
source is the @filepath{main.ss} file in the @filepath{scheme}
collection.
@examples[
(module m scheme
(require scheme/date)
(printf "Today is ~s\n"
(date->string (seconds->date (current-seconds)))))
(require 'm)
]}
@; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@specsubform[rel-string]{
A string @tech{module path} is a relative path using Unix-style
conventions: @litchar{/} is the path separator, @litchar{..} refers to
the parent directory, and @litchar{.} refers to the same
directory. The @scheme[rel-string] must not start or end with a path
separator.
directory. The @racket[rel-string] must not start or end with a path
separator. If the path has no suffix, @filepath{.rkt} is added
automatically.
The path is relative to the enclosing file, if any, or it is relative
to the current directory. (More precisely, the path is relative to the
value of @scheme[(current-load-relative-directory)], which is set
value of @racket[(current-load-relative-directory)], which is set
while loading a file.)
@secref["module-basics"] shows examples using relative paths.
}
If a relative path ends with a @filepath{.ss} suffix, it is converted
to @filepath{.rkt}. If the file that implements the referenced module
actually ends in @filepath{.ss}, the suffix will be changed back when
attempting to load the file (but a @filepath{.rkt} suffix takes
precedence). This two-way conversion provides compatibility with older
versions of Racket.}
@; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@specsubform[id]{
A @tech{module path} that is an unquoted identifier refers to an
installed library. The @racket[id] is constrained to contain only
ASCII letters, ASCII numbers, @litchar{+}, @litchar{-}, @litchar{_},
and @litchar{/}, where @litchar{/} separates path elements within the
identifier. The elements refer to @tech{collection}s and
sub-@tech{collections}, instead of directories and sub-directories.
An example of this form is @racket[racket/date]. It refers to the
module whose source is the @filepath{date.rkt} file in the
@filepath{racket} collection, which is installed as part of
Racket. The @filepath{.rkt} suffix is added automatically.
Another example of this form is @racketmodname[racket], which is commonly
used at the initial import. The path @racketmodname[racket] is shorthand for
@racket[racket/main]; when an @racket[id] has no @litchar{/}, then
@racket[/main] is automatically added to the end. Thus,
@racketmodname[racket] or @racket[racket/main] refers to the module whose
source is the @filepath{main.rkt} file in the @filepath{racket}
collection.
@examples[
(module m racket
(require racket/date)
(printf "Today is ~s\n"
(date->string (seconds->date (current-seconds)))))
(require 'm)
]
When the full path of a module ends with @filepath{.rkt}, if no such
file exists but one does exist with the @filepath{.ss} suffix, then
the @filepath{.ss} suffix is substituted automatically. This
transformation provides compatibility with older versions of Racket.}
@; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@specsubform[#:literals (lib)
(lib rel-string)]{
Like an unquoted-identifier path, but expressed as a string instead of
an identifier. Also, the @scheme[rel-string] can end with a file
suffix, in case the relevant suffix is not @filepath{.ss}.
an identifier. Also, the @racket[rel-string] can end with a file
suffix, in which case @filepath{.rkt} is not automatically added.
Example of this form include @scheme[(lib "scheme/date.ss")] and
@scheme[(lib "scheme/date")], which are equivalent to
@scheme[scheme/date]. Other examples include @scheme[(lib "scheme")],
@scheme[(lib "scheme/main")], and @scheme[(lib "scheme/main.ss")],
which are all equivalent to @scheme[scheme].
Example of this form include @racket[(lib "racket/date.rkt")] and
@racket[(lib "racket/date")], which are equivalent to
@racket[racket/date]. Other examples include @racket[(lib "racket")],
@racket[(lib "racket/main")], and @racket[(lib "racket/main.rkt")],
which are all equivalent to @racketmodname[racket].
@examples[
(module m (lib "scheme")
(require (lib "scheme/date.ss"))
(module m (lib "racket")
(require (lib "racket/date.rkt"))
(printf "Today is ~s\n"
(date->string (seconds->date (current-seconds)))))
@ -106,17 +118,17 @@ Accesses a third-party library that is distributed through the
@|PLaneT| server. The library is downloaded the first time that it is
needed, and then the local copy is used afterward.
The @scheme[id] encodes several pieces of information separated by a
The @racket[id] encodes several pieces of information separated by a
@litchar{/}: the package owner, then package name with optional
version information, and an optional path to a specific library with
the package. Like @scheme[id] as shorthand for a @scheme[lib] path, a
@filepath{.ss} suffix is added automatically, and @schemeidfont{/main}
the package. Like @racket[id] as shorthand for a @racket[lib] path, a
@filepath{.rkt} suffix is added automatically, and @racketidfont{/main}
is used as the path if no sub-path element is supplied.
@examples[
(eval:alts
(module m (lib "scheme")
(code:comment @#,t{Use @filepath{schematics}'s @filepath{random.plt} 1.0, file @filepath{random.ss}:})
(module m (lib "racket")
(code:comment @#,t{Use @filepath{schematics}'s @filepath{random.plt} 1.0, file @filepath{random.rkt}:})
(require (planet schematics/random:1/random))
(display (random-gaussian)))
(void))
@ -124,16 +136,23 @@ is used as the path if no sub-path element is supplied.
(require 'm)
(display 0.9050686838895684))
]
}
As with other forms, an implementation file ending with @filepath{.ss}
can be substituted automatically if no implementation file ending with
@filepath{.rkt} exists.}
@; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@specsubform[#:literals (planet)
(planet package-string)]{
Like the symbol form of a @scheme[planet], but using a string instead
of an identifier. Also, the @scheme[package-string] can end with a
file suffix, in case the relevant suffix is not @filepath{.ss}.
}
Like the symbol form of a @racket[planet], but using a string instead
of an identifier. Also, the @racket[package-string] can end with a
file suffix, in which case @filepath{.rkt} is not added.
As with other forms, an @filepath{.ss} extension is converted to
@filepath{.rkt}, while an implementation file ending with
@filepath{.ss} can be substituted automatically if no implementation
file ending with @filepath{.rkt} exists.}
@; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@specsubform/subs[#:literals (planet = + -)
@ -145,45 +164,48 @@ file suffix, in case the relevant suffix is not @filepath{.ss}.
(- nat)])]{
A more general form to access a library from the @|PLaneT| server. In
this general form, a @|PLaneT| reference starts like a @scheme[lib]
this general form, a @|PLaneT| reference starts like a @racket[lib]
reference with a relative path, but the path is followed by
information about the producer, package, and version of the
library. The specified package is downloaded and installed on demand.
The @scheme[vers]es specify a constraint on the acceptable version of
The @racket[vers]es specify a constraint on the acceptable version of
the package, where a version number is a sequence of non-negative
integers, and the constraints determine the allowable values for each
element in the sequence. If no constraint is provided for a particular
element, then any version is allowed; in particular, omitting all
@scheme[vers]es means that any version is acceptable. Specifying at
least one @scheme[vers] is strongly recommended.
@racket[vers]es means that any version is acceptable. Specifying at
least one @racket[vers] is strongly recommended.
For a version constraint, a plain @scheme[nat] is the same as
@scheme[(+ nat)], which matches @scheme[nat] or higher for the
corresponding element of the version number. A @scheme[(_start-nat
_end-nat)] matches any number in the range @scheme[_start-nat] to
@scheme[_end-nat], inclusive. A @scheme[(= nat)] matches only exactly
@scheme[nat]. A @scheme[(- nat)] matches @scheme[nat] or lower.
For a version constraint, a plain @racket[nat] is the same as
@racket[(+ nat)], which matches @racket[nat] or higher for the
corresponding element of the version number. A @racket[(_start-nat
_end-nat)] matches any number in the range @racket[_start-nat] to
@racket[_end-nat], inclusive. A @racket[(= nat)] matches only exactly
@racket[nat]. A @racket[(- nat)] matches @racket[nat] or lower.
@examples[
(eval:alts
(module m (lib "scheme")
(require (planet "random.ss" ("schematics" "random.plt" 1 0)))
(module m (lib "racket")
(require (planet "random.rkt" ("schematics" "random.plt" 1 0)))
(display (random-gaussian)))
(void))
(eval:alts
(require 'm)
(display 0.9050686838895684))
]
}
The automatic @filepath{.ss} and @filepath{.rkt} conversions apply as
with other forms.}
@; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@specsubform[#:literals (file)
(file string)]{
Refers to a file, where @scheme[string] is a relative or absolute path
Refers to a file, where @racket[string] is a relative or absolute path
using the current platform's conventions. This form is not portable,
and it should @italic{not} be used when a plain, portable
@scheme[rel-string] suffices.
@racket[rel-string] suffices.
}
The automatic @filepath{.ss} and @filepath{.rkt} conversions apply as
with other forms.}

View File

@ -3,31 +3,31 @@
scribble/eval
"guide-utils.ss")
@title[#:tag "module-provide"]{Exports: @scheme[provide]}
@title[#:tag "module-provide"]{Exports: @racket[provide]}
By default, all of a module's definitions are private to the
module. The @scheme[provide] form specifies definitions to be made
available where the module is @scheme[require]d.
module. The @racket[provide] form specifies definitions to be made
available where the module is @racket[require]d.
@specform[(provide provide-spec ...)]{}
A @scheme[provide] form can only appear at module level (i.e., in the
immediate body of a @scheme[module]). Specifying multiple
@scheme[_provide-spec]s in a single @scheme[provide] is exactly the
same as using multiple @scheme[provide]s each with a single
@scheme[_provide-spec].
A @racket[provide] form can only appear at module level (i.e., in the
immediate body of a @racket[module]). Specifying multiple
@racket[_provide-spec]s in a single @racket[provide] is exactly the
same as using multiple @racket[provide]s each with a single
@racket[_provide-spec].
Each identifier can be exported at most once from a module across all
@scheme[provide]s within the module. More precisely, the external name
@racket[provide]s within the module. More precisely, the external name
for each export must be distinct; the same internal binding can be
exported multiple times with different external names.
The allowed shape of a @scheme[_provide-spec] is defined recursively:
The allowed shape of a @racket[_provide-spec] is defined recursively:
@;------------------------------------------------------------------------
@specspecsubform[identifier]{
In its simplest form, a @scheme[_provide-spec] indicates a binding
In its simplest form, a @racket[_provide-spec] indicates a binding
within its module to be exported. The binding can be from either a
local definition, or from an import.
@ -37,9 +37,9 @@ local definition, or from an import.
@specspecsubform[#:literals(rename-out)
(rename-out [orig-id export-id] ...)]{
A @scheme[rename-out] form is similar to just specifying an identifier,
but the exported binding @scheme[orig-id] is given a different name,
@scheme[export-id], to importing modules.
A @racket[rename-out] form is similar to just specifying an identifier,
but the exported binding @racket[orig-id] is given a different name,
@racket[export-id], to importing modules.
}
@ -48,11 +48,11 @@ but the exported binding @scheme[orig-id] is given a different name,
@specspecsubform[#:literals(struct-out)
(struct-out struct-id)]{
A @scheme[struct-out] form exports the bindings created by
@scheme[(define-struct struct-id ....)].
A @racket[struct-out] form exports the bindings created by
@racket[(struct struct-id ....)].
@guideother{See @secref["define-struct"] for information on
@scheme[define-struct].}
@racket[define-struct].}
}
@ -61,15 +61,15 @@ A @scheme[struct-out] form exports the bindings created by
@specspecsubform[#:literals (all-defined-out)
(all-defined-out)]{
The @scheme[all-defined-out] shorthand exports all bindings that are
The @racket[all-defined-out] shorthand exports all bindings that are
defined within the exporting module (as opposed to imported).
Use of the @scheme[all-defined-out] shorthand is generally
Use of the @racket[all-defined-out] shorthand is generally
discouraged, because it makes less clear the actual exports for a
module, and because PLT Scheme programmers get into the habit of
module, and because Racket programmers get into the habit of
thinking that definitions can be added freely to a module without
affecting its public interface (which is not the case when
@scheme[all-defined-out] is used).
@racket[all-defined-out] is used).
}
@ -77,13 +77,13 @@ affecting its public interface (which is not the case when
@specspecsubform[#:literals (all-from-out)
(all-from-out module-path)]{
The @scheme[all-from-out] shorthand exports all bindings in the module
that were imported using a @scheme[_require-spec] that is based on
@scheme[module-path].
The @racket[all-from-out] shorthand exports all bindings in the module
that were imported using a @racket[_require-spec] that is based on
@racket[module-path].
Although different @scheme[module-path]s could refer to the same
file-based module, re-exporting with @scheme[all-from-out] is based
specifically on the @scheme[module-path] reference, and not the module
Although different @racket[module-path]s could refer to the same
file-based module, re-exporting with @racket[all-from-out] is based
specifically on the @racket[module-path] reference, and not the module
that is actually referenced.
}
@ -92,8 +92,8 @@ that is actually referenced.
@specspecsubform[#:literals (except-out)
(except-out provide-spec id ...)]{
Like @scheme[provide-spec], but omitting the export of each
@scheme[id], where @scheme[id] is the external name of the binding to
Like @racket[provide-spec], but omitting the export of each
@racket[id], where @racket[id] is the external name of the binding to
omit.
}
@ -103,7 +103,7 @@ omit.
@specspecsubform[#:literals (prefix-out)
(prefix-out prefix-id provide-spec)]{
Like @scheme[provide-spec], but adding @scheme[prefix-id] to the
Like @racket[provide-spec], but adding @racket[prefix-id] to the
beginning of the external name for each exported binding.
}

View File

@ -3,44 +3,44 @@
scribble/eval
"guide-utils.ss")
@title[#:tag "module-require"]{Imports: @scheme[require]}
@title[#:tag "module-require"]{Imports: @racket[require]}
The @scheme[require] form imports from another module. A
@scheme[require] form can appear within a module, in which case it
The @racket[require] form imports from another module. A
@racket[require] form can appear within a module, in which case it
introduces bindings from the specified module into importing module. A
@scheme[require] form can also appear at the top level, in which case
@racket[require] form can also appear at the top level, in which case
it both imports bindings and @deftech{instantiates} the specified
module; that is, it evaluates the body definitions and expressions of
the specified module, if they have not been evaluated already.
A single @scheme[require] can specify multiple imports at once:
A single @racket[require] can specify multiple imports at once:
@specform[(require require-spec ...)]{}
Specifying multiple @scheme[_require-spec]s in a single
@scheme[require] is essentially the same as using multiple
@scheme[require]s, each with a single @scheme[_require-spec]. The
Specifying multiple @racket[_require-spec]s in a single
@racket[require] is essentially the same as using multiple
@racket[require]s, each with a single @racket[_require-spec]. The
difference is minor, and confined to the top-level: a single
@scheme[require] can import a given identifier at most once, whereas a
separate @scheme[require] can replace the bindings of a previous
@scheme[require] (both only at the top level, outside of a module).
@racket[require] can import a given identifier at most once, whereas a
separate @racket[require] can replace the bindings of a previous
@racket[require] (both only at the top level, outside of a module).
The allowed shape of a @scheme[_require-spec] is defined recursively:
The allowed shape of a @racket[_require-spec] is defined recursively:
@;------------------------------------------------------------------------
@specspecsubform[module-path]{
In its simplest form, a @scheme[_require-spec] is a
@scheme[module-path] (as defined in the previous section,
In its simplest form, a @racket[_require-spec] is a
@racket[module-path] (as defined in the previous section,
@secref["module-paths"]). In this case, the bindings introduced
by @scheme[require] are determined by @scheme[provide] declarations
within each module referenced by each @scheme[module-path].
by @racket[require] are determined by @racket[provide] declarations
within each module referenced by each @racket[module-path].
@examples[
(module m scheme
(module m racket
(provide color)
(define color "blue"))
(module n scheme
(module n racket
(provide size)
(define size 17))
(require 'm 'n)
@ -55,15 +55,15 @@ within each module referenced by each @scheme[module-path].
([id-maybe-renamed id
[orig-id bind-id]])]{
An @scheme[only-in] form limits the set of bindings that would be introduced
by a base @scheme[require-spec]. Also, @scheme[only-in] optionally
renames each binding that is preserved: in a @scheme[[orig-id
bind-id]] form, the @scheme[orig-id] refers to a binding implied by
@scheme[require-spec], and @scheme[bind-id] is the name that will be
bound in the importing context instead of @scheme[bind-id].
An @racket[only-in] form limits the set of bindings that would be introduced
by a base @racket[require-spec]. Also, @racket[only-in] optionally
renames each binding that is preserved: in a @racket[[orig-id
bind-id]] form, the @racket[orig-id] refers to a binding implied by
@racket[require-spec], and @racket[bind-id] is the name that will be
bound in the importing context instead of @racket[bind-id].
@examples[
(module m (lib "scheme")
(module m (lib "racket")
(provide tastes-great?
less-filling?)
(define tastes-great? #t)
@ -79,8 +79,8 @@ less-filling?
@specspecsubform[#:literals (except-in)
(except-in require-spec id ...)]{
This form is the complement of @scheme[only]: it excludes specific
bindings from the set specified by @scheme[require-spec].
This form is the complement of @racket[only]: it excludes specific
bindings from the set specified by @racket[require-spec].
}
@ -88,31 +88,31 @@ bindings from the set specified by @scheme[require-spec].
@specspecsubform[#:literals (rename-in)
(rename-in require-spec [orig-id bind-id] ...)]{
This form supports renaming like @scheme[only-in], but leaving alone
identifiers from @scheme[require-spec] that are not mentioned as an
@scheme[orig-id]. }
This form supports renaming like @racket[only-in], but leaving alone
identifiers from @racket[require-spec] that are not mentioned as an
@racket[orig-id]. }
@;------------------------------------------------------------------------
@specspecsubform[#:literals (prefix-in)
(prefix-in prefix-id require-spec)]{
This is a shorthand for renaming, where @scheme[prefix-id] is added to
the front of each identifier specified by @scheme[require-spec].
This is a shorthand for renaming, where @racket[prefix-id] is added to
the front of each identifier specified by @racket[require-spec].
}
The @scheme[only-in], @scheme[except-in], @scheme[rename-in], and
@scheme[prefix-in] forms can be nested to implement more complex
The @racket[only-in], @racket[except-in], @racket[rename-in], and
@racket[prefix-in] forms can be nested to implement more complex
manipulations of imported bindings. For example,
@schemeblock[(require (prefix-in m: (except-in 'm ghost)))]
@racketblock[(require (prefix-in m: (except-in 'm ghost)))]
imports all bindings that @scheme[m]
exports, except for the @scheme[ghost] binding, and with local names
that are prefixed with @scheme[m:].
imports all bindings that @racket[m]
exports, except for the @racket[ghost] binding, and with local names
that are prefixed with @racket[m:].
Equivalently, the @scheme[prefix-in] could be applied before
@scheme[except-in], as long as the omission with @scheme[except-in] is
specified using the @scheme[m:] prefix:
Equivalently, the @racket[prefix-in] could be applied before
@racket[except-in], as long as the omission with @racket[except-in] is
specified using the @racket[m:] prefix:
@schemeblock[(require (except-in (prefix m: 'm) m:ghost))]
@racketblock[(require (except-in (prefix m: 'm) m:ghost))]

View File

@ -5,14 +5,14 @@
@title[#:tag "module-set"]{Assignment and Redefinition}
The use of @scheme[set!] on variables defined within a module is
The use of @racket[set!] on variables defined within a module is
limited to the body of the defining module. That is, a module is
allowed to change the value of its own definitions, and such changes
are visible to importing modules. However, an importing context is not
allowed to change the value of an imported binding.
@examples[
(module m scheme
(module m racket
(provide counter increment!)
(define counter 0)
(define (increment!)
@ -26,26 +26,26 @@ allowed to change the value of an imported binding.
As the above example illustrates, a module can always grant others the
ability to change its exports by providing a mutator function, such as
@scheme[increment!].
@racket[increment!].
The prohibition on assignment of imported variables helps support
modular reasoning about programs. For example, in the module,
@schemeblock[
(module m scheme
@racketblock[
(module m racket
(provide rx:fish fishy-string?)
(define rx:fish #rx"fish")
(define (fishy-string? s)
(regexp-match? s rx:fish)))
]
the function @scheme[fishy-string?] will always match strings that
contain ``fish'', no matter how other modules use the @scheme[rx:fish]
the function @racket[fishy-string?] will always match strings that
contain ``fish'', no matter how other modules use the @racket[rx:fish]
binding. For essentially the same reason that it helps programmers,
the prohibition on assignment to imports also allows many programs to
be executed more efficiently.
Along the same lines, when a module contains no @scheme[set!] of a
Along the same lines, when a module contains no @racket[set!] of a
particular identifier that is defined within the module, then the
identifier is considered a @defterm{constant} that cannot be
changed---not even by re-declaring the module.
@ -54,30 +54,30 @@ Consequently, re-declaration of a module is not generally allowed.
For file-based modules, simply changing the file does not lead to a
re-declaration in any case, because file-based modules are loaded on
demand, and the previously loaded declarations satisfy future
requests. It is possible to use Scheme's reflection support to
requests. It is possible to use Racket's reflection support to
re-declare a module, however, and non-file modules can be re-declared
in the @tech{REPL}; in such cases, the re-declaration may fail if it
involves the re-definition of a previously constant binding.
@interaction[
(module m scheme
(module m racket
(define pie 3.141597))
(require 'm)
(module m scheme
(module m racket
(define pie 3))
]
For exploration and debugging purposes, the Scheme reflective layer
provides a @scheme[compile-enforce-module-constants] parameter
For exploration and debugging purposes, the Racket reflective layer
provides a @racket[compile-enforce-module-constants] parameter
to disable the enforcement of constants.
@interaction[
(compile-enforce-module-constants #f)
(module m2 scheme
(module m2 racket
(provide pie)
(define pie 3.141597))
(require 'm2)
(module m2 scheme
(module m2 racket
(provide pie)
(define pie 3))
(compile-enforce-module-constants #t)

View File

@ -8,14 +8,14 @@
@title{Module Syntax}
The @litchar{#lang} at the start of a module file begins a shorthand
for a @scheme[module] form, much like @litchar{'} is a shorthand for a
@scheme[quote] form. Unlike @litchar{'}, the @litchar{#lang}
for a @racket[module] form, much like @litchar{'} is a shorthand for a
@racket[quote] form. Unlike @litchar{'}, the @litchar{#lang}
shorthand does not work well in a @tech{REPL}, in part because it must be
terminated by an end-of-file, but also because the longhand expansion
of @litchar{#lang} depends on the name of the enclosing file.
@;------------------------------------------------------------------------
@section[#:tag "module-syntax"]{The @scheme[module] Form}
@section[#:tag "module-syntax"]{The @racket[module] Form}
The longhand form of a module declaration, which works in a
@tech{REPL} as well as a file, is
@ -25,29 +25,29 @@ The longhand form of a module declaration, which works in a
decl ...)
]
where the @scheme[_name-id] is a name for the module,
@scheme[_initial-module-path] is an initial import, and each
@scheme[_decl] is an import, export, definition, or expression. In
the case of a file, @scheme[_name-id] must match the name of the
where the @racket[_name-id] is a name for the module,
@racket[_initial-module-path] is an initial import, and each
@racket[_decl] is an import, export, definition, or expression. In
the case of a file, @racket[_name-id] must match the name of the
containing file, minus its directory path or file extension.
The @scheme[_initial-module-path] is needed because even the
@scheme[require] form must be imported for further use in the module
body. In other words, the @scheme[_initial-module-path] import
The @racket[_initial-module-path] is needed because even the
@racket[require] form must be imported for further use in the module
body. In other words, the @racket[_initial-module-path] import
bootstraps the syntax available in the body. The most commonly used
@scheme[_initial-module-path] is @scheme[scheme], which supplies most
of the bindings described in this guide, including @scheme[require],
@scheme[define], and @scheme[provide]. Another commonly used
@scheme[_initial-module-path] is @scheme[scheme/base], which provides
@racket[_initial-module-path] is @racketmodname[racket], which supplies most
of the bindings described in this guide, including @racket[require],
@racket[define], and @racket[provide]. Another commonly used
@racket[_initial-module-path] is @racketmodname[racket/base], which provides
less functionality, but still much of the most commonly needed
functions and syntax.
For example, the @filepath{cake.ss} example of the
For example, the @filepath{cake.rkt} example of the
@seclink["module-basics"]{previous section} could be written as
@schemeblock+eval[
@racketblock+eval[
#:eval cake-eval
(module cake scheme
(module cake racket
(provide print-cake)
(define (print-cake n)
@ -57,8 +57,8 @@ For example, the @filepath{cake.ss} example of the
(printf "---~a---\n" (make-string n #\-))))
]
Furthermore, this @scheme[module] form can be evaluated in a
@tech{REPL} to declare a @scheme[cake] module that is not associated
Furthermore, this @racket[module] form can be evaluated in a
@tech{REPL} to declare a @racket[cake] module that is not associated
with any file. To refer to such an unassociated module, quote the
module name:
@ -70,53 +70,53 @@ module name:
Declaring a module does not immediately evaluate the body definitions
and expressions of the module. The module must be explicitly
@scheme[require]d at the top level to trigger evaluation. After
evaluation is triggered once, later @scheme[require]s do not
@racket[require]d at the top level to trigger evaluation. After
evaluation is triggered once, later @racket[require]s do not
re-evaluate the module body.
@examples[
(module hi scheme
(module hi racket
(printf "Hello\n"))
(require 'hi)
(require 'hi)
]
@;------------------------------------------------------------------------
@section[#:tag "hash-lang"]{The @schememodfont{#lang} Shorthand}
@section[#:tag "hash-lang"]{The @racketmodfont{#lang} Shorthand}
The body of a @schememodfont{#lang} shorthand has no specific syntax,
The body of a @racketmodfont{#lang} shorthand has no specific syntax,
because the syntax is determined by the language name that follows
@schememodfont{#lang}.
@racketmodfont{#lang}.
In the case of @schememodfont{#lang} @schememodname[scheme], the syntax
In the case of @racketmodfont{#lang} @racketmodname[racket], the syntax
is
@schememod[
scheme
@racketmod[
racket
_decl ...]
which reads the same as
@schemeblock[
(module _name scheme
@racketblock[
(module _name racket
_decl ...)
]
where @scheme[_name] is derived from the name of the file that
contains the @schememodfont{#lang} form.
where @racket[_name] is derived from the name of the file that
contains the @racketmodfont{#lang} form.
The @schememodfont{#lang} @scheme[scheme/base] form has the same
syntax as @schememodfont{#lang} @schememodname[scheme], except that
the longhand expansion uses @scheme[scheme/base] instead of
@scheme[scheme]. The @schememodfont{#lang} @scheme[honu] form, in
The @racketmodfont{#lang} @racketmodname[racket/base] form has the same
syntax as @racketmodfont{#lang} @racketmodname[racket], except that
the longhand expansion uses @racketmodname[racket/base] instead of
@racketmodname[racket]. The @racketmodfont{#lang} @racket[honu] form, in
contrast, has a completely different syntax that doesn't even look
like Scheme, and which we do not attempt to describe in this guide.
like Racket, and which we do not attempt to describe in this guide.
Unless otherwise specified, a module that is documented as a
``language'' using the @schememodfont{#lang} notation will expand to
@scheme[module] in the same way as @schememodfont{#lang}
@schememodname[scheme]. The documented language name can be used
directly with @scheme[module] or @scheme[require], too.
``language'' using the @racketmodfont{#lang} notation will expand to
@racket[module] in the same way as @racketmodfont{#lang}
@racketmodname[racket]. The documented language name can be used
directly with @racket[module] or @racket[require], too.
@; ----------------------------------------------------------------------

View File

@ -6,7 +6,7 @@
@title[#:tag "modules" #:style 'toc]{Modules}
Modules let you organize Scheme code into multiple files and reusable
Modules let you organize Racket code into multiple files and reusable
libraries.
@local-table-of-contents[]

View File

@ -5,7 +5,7 @@
@title[#:tag "numbers"]{Numbers}
A Scheme @deftech{number} is either exact or inexact:
A Racket @deftech{number} is either exact or inexact:
@itemize[
@ -13,16 +13,16 @@ A Scheme @deftech{number} is either exact or inexact:
@itemize[
@item{an arbitrarily large or small integer, such as @scheme[5],
@scheme[99999999999999999], or @scheme[-17];}
@item{an arbitrarily large or small integer, such as @racket[5],
@racket[99999999999999999], or @racket[-17];}
@item{a rational that is exactly the ratio of two arbitrarily
small or large integers, such as @scheme[1/2],
@scheme[99999999999999999/2], or @scheme[-3/4]; or}
small or large integers, such as @racket[1/2],
@racket[99999999999999999/2], or @racket[-3/4]; or}
@item{a complex number with exact real and imaginary parts
(where the imaginary part is not zero), such as @scheme[1+2i] or
@scheme[1/2+3/4i].}
(where the imaginary part is not zero), such as @racket[1+2i] or
@racket[1/2+3/4i].}
]}
@ -31,14 +31,14 @@ A Scheme @deftech{number} is either exact or inexact:
@itemize[
@item{an IEEE floating-point representation of a number, such
as @scheme[2.0] or @scheme[3.14e87], where the IEEE
as @racket[2.0] or @racket[3.14e87], where the IEEE
infinities and not-a-number are written
@scheme[+inf.0], @scheme[-inf.0], and @scheme[+nan.0]
(or @schemevalfont{-nan.0}); or}
@racket[+inf.0], @racket[-inf.0], and @racket[+nan.0]
(or @racketvalfont{-nan.0}); or}
@item{a complex number with real and imaginary parts that are
IEEE floating-point representations, such as
@scheme[2.0+3.0i] or @scheme[-inf.0+nan.0i]; as a
@racket[2.0+3.0i] or @racket[-inf.0+nan.0i]; as a
special case, an inexact complex number can have an
exact zero real part with an inexact imaginary part.}
@ -57,16 +57,16 @@ interpretation of digits.
@examples[
0.5
(eval:alts @#,schemevalfont{#e0.5} 1/2)
(eval:alts @#,schemevalfont{#x03BB} #x03BB)
(eval:alts @#,racketvalfont{#e0.5} 1/2)
(eval:alts @#,racketvalfont{#x03BB} #x03BB)
]
Computations that involve an inexact number produce inexact results,
so that inexactness acts as a kind of taint on numbers. Beware,
however, that Scheme offers no ``inexact booleans'', so computations
however, that Racket offers no ``inexact booleans,'' so computations
that branch on the comparison of inexact numbers can nevertheless
produce exact results. The procedures @scheme[exact->inexact] and
@scheme[inexact->exact] convert between the two
produce exact results. The procedures @racket[exact->inexact] and
@racket[inexact->exact] convert between the two
types of numbers.
@examples[
@ -76,9 +76,9 @@ types of numbers.
(inexact->exact 0.1)
]
Inexact results are also produced by procedures such as @scheme[sqrt],
@scheme[log], and @scheme[sin] when an exact result would require
representing real numbers that are not rational. Scheme can represent
Inexact results are also produced by procedures such as @racket[sqrt],
@racket[log], and @racket[sin] when an exact result would require
representing real numbers that are not rational. Racket can represent
only rational numbers and complex numbers with rational parts.
@examples[
@ -105,9 +105,9 @@ with inexact numbers.
The number categories @deftech{integer}, @deftech{rational},
@deftech{real} (always rational), and @deftech{complex} are defined in
the usual way, and are recognized by the procedures @scheme[integer?],
@scheme[rational?], @scheme[real?], and @scheme[complex?], in addition
to the generic @scheme[number?]. A few mathematical procedures accept
the usual way, and are recognized by the procedures @racket[integer?],
@racket[rational?], @racket[real?], and @racket[complex?], in addition
to the generic @racket[number?]. A few mathematical procedures accept
only real numbers, but most implement standard extensions to complex
numbers.
@ -123,10 +123,10 @@ numbers.
(sin -5+2i)
]
The @scheme[=] procedure compares numbers for numerical equality. If
The @racket[=] procedure compares numbers for numerical equality. If
it is given both inexact and exact numbers to compare, it essentially
converts the inexact numbers to exact before comparing. The
@scheme[eqv?] (and therefore @scheme[equal?]) procedure, in contrast,
@racket[eqv?] (and therefore @racket[equal?]) procedure, in contrast,
compares numbers considering both exactness and numerical equality.
@examples[
@ -137,8 +137,8 @@ compares numbers considering both exactness and numerical equality.
Beware of comparisons involving inexact numbers, which by their nature
can have surprising behavior. Even apparently simple inexact numbers
may not mean what you think they mean; for example, while a base-2
IEEE floating-point number can represent @scheme[1/2] exactly, it
can only approximate @scheme[1/10]:
IEEE floating-point number can represent @racket[1/2] exactly, it
can only approximate @racket[1/10]:
@examples[
(= 1/2 0.5)

View File

@ -11,7 +11,8 @@ procedures extract the first and second elements of the pair,
respectively. The @scheme[pair?] predicate recognizes pairs.
Some pairs print by wrapping parentheses around the printed forms of
the two pair elements, putting a @litchar{.} between them.
the two pair elements, putting a @litchar{`} at the beginning and a
@litchar{.} between the elements.
@examples[
(cons 1 2)
@ -27,8 +28,8 @@ or it is a pair whose first element is a list element and whose second
element is a list. The @scheme[list?] predicate recognizes lists. The
@scheme[null?] predicate recognizes the empty list.
A list prints as a pair of parentheses wrapped around the list
elements.
A list prints as a @litchar{`} followed by a pair of parentheses
wrapped around the list elements.
@examples[
null
@ -38,13 +39,13 @@ null
(list? (cons 1 2))
]
An expression with @litchar{'} followed by the printed form of a pair
or list produces a pair or list constant.
The @scheme[display] function prints a pair or list without a leading
@litchar{`}:
@examples[
'()
'(1 . 2)
'(1 2 3)
(display (cons 1 2))
(display null)
(display (list 1 2 3))
]
Pairs are immutable (contrary to Lisp tradition), and @scheme[pair?]

View File

@ -4,140 +4,160 @@
"guide-utils.ss"
(for-label (only-in mzscheme fluid-let)))
@title[#:tag "parameterize"]{Dynamic Binding: @scheme[parameterize]}
@(define param-eval (make-base-eval))
@scheme[parameterize] is used to have values that are ``dynamically scoped''.
You get a parameter with @scheme[make-parameter]. The parameter itself
behaves as a function: call it with no inputs and you get its value,
call it with one value and it will set the value. The settings that are
adjusted by a @scheme[parameterize] form are called @deftech{parameters}.
For example:
@title[#:tag "parameterize"]{Dynamic Binding: @racket[parameterize]}
@margin-note{The term ``parameter'' is sometimes used to refer to the
arguments of a function, but ``parameter'' in PLT Scheme
has the more specific meaning described here.}
@refalso["parameters"]{@racket[parameterize]}
@examples[
(define p (make-parameter "blah"))
(p)
(p "meh")
(p)]
Many functions (including many primitive ones) use parameters as a way
to customize their behavior. For example @scheme[printf] will print text
using the port that is the value of the @scheme[current-output-port]
parameter. Now, say that you have some function that prints
something:
@examples[
(define (foo x) (printf "the value of x is ~s\n"))
]
You usually call this function and see something printed on the screen
-- but in some cases you want to use it to print something to a file
or whatever. You could do this:
@examples[
(define (bar)
(let ([old-stdout (current-output-port)])
(current-output-port my-own-port)
(foo some-value)
(current-output-port old-stdout)))
]
One problem with this is that it is tedious to do -- but that's easily
solved with a macro. (In fact, PLT still has a construct that does
that in some languages: @scheme[fluid-let].) But there are more problems
here: what happens if the call to @scheme[foo] results in a runtime error?
This might leave the system in a bad state, where all output goes to
your port (and you won't even see a problem, since it won't print
anything). A solution for that (which @scheme[fluid-let] uses too) is to
protect the saving/restoring of the parameter with @scheme[dynamic-wind],
which makes sure that if there's an error (and more, if you know about
continuations) then the value is still restored.
So the question is what's the point of having parameters instead of
just using globals and @scheme[fluid-let]? There are two more problems that
you cannot solve with just globals. One is what happens when you have
multiple threads -- in this case, setting the value temporarily will
affect other threads, which may still want to print to the standard
output. Parameters solve this by having a specific value per-thread.
What happens is that each thread ``inherits'' the value from the thread
that created it, and changes in one thread are visible only in that
thread.
The other problem is more subtle. Say that you have a parameter with
a numeric value, and you want to do the following:
@examples[
(define (foo)
(parameterize ([p 'any-expression-goes-here])
(foo)))
]
In Scheme, ``tail calls'' are important -- they are the basic tool for
creating loops and much more. @scheme[parameterize] does some magic that
allows it to change the parameter value temporarily but still preserve
these tail calls. For example, in the above case, you @bold{will} get an
infinite loop, rather than get a stack overflow error -- what happens
is that each of these @scheme[parameterize] expressions can somehow detect
when there's an earlier @scheme[parameterize] that no longer needs to do its
cleanup.
Finally, @scheme[parameterize] actually uses two important parts of PLT to do
its job: it uses thread cells to implement per-thread values, and it
uses continuation marks to be able to preserve tail-calls. Each of
these features is useful in itself.
The @racket[parameterize] form associates a new value with a
@deftech{parameter} during the evaluation of @racket[_body]
expressions:
@specform[(parameterize ([parameter-expr value-expr] ...)
body ...+)]
The result of a @scheme[parameterize] form is the result of the last
@scheme[_body] expression. While the @scheme[_body] expressions are
evaluated, the parameter produced by each @scheme[_parameter-expr] is
set to the result of the corresponding @scheme[_value-expr].
@margin-note{The term ``parameter'' is sometimes used to refer to the
arguments of a function, but ``parameter'' in Racket
has the more specific meaning described here.}
Many parameters are built in. For example, the
@scheme[error-print-width] parameter controls how many characters of a
value are printed in an error message (in case the printed form of the
value is very large):
For example, the @racket[error-print-width] parameter controls how
many characters of a value are printed in an error message:
@interaction[
(parameterize ([error-print-width 10])
(parameterize ([error-print-width 5])
(car (expt 10 1024)))
(parameterize ([error-print-width 5])
(parameterize ([error-print-width 10])
(car (expt 10 1024)))
]
The @scheme[error-print-width] parameter acts like a kind of default
argument to the function that formats error messages. This
parameter-based argument can be configured far from the actual call to
the error-formatting function, which in this case is called deep
within the implementation of @scheme[car].
The @scheme[parameterize] form adjusts the value of a parameter only
while evaluating its body expressions. After the body produces a
value, the parameter reverts to its previous value. If control escapes
from the body due to an exception, as in the above example, then the
parameter value is restored in that case, too. Finally, parameter
values are thread-specific, so that multiple threads do not interfere
with each others' settings.
Use @scheme[make-parameter] to create a new parameter that works with
@scheme[parameterize]. The argument to @scheme[make-parameter] is the
value of the parameter when it is not otherwise set by
@scheme[parameterize]. To access the current value of the parameter,
call it like a function.
More generally, parameters implement a kind of dynamic binding. The
@racket[make-parameter] function takes any value and returns a new
parameter that is initialized to the given value. Applying the
parameter as a function returns its current value:
@interaction[
(define favorite-flavor (make-parameter 'chocolate))
(favorite-flavor)
(define (scoop)
`(scoop of ,(favorite-flavor)))
(define (ice-cream n)
(list (scoop) (scoop) (scoop)))
(parameterize ([favorite-flavor 'strawberry])
(ice-cream 3))
(ice-cream 3)
#:eval param-eval
(define location (make-parameter "here"))
(location)
]
In a @scheme[parameterize] form, each @racket[_parameter-expr] must
produce a parameter. During the evaluation of the @scheme[body]s, each
specified parameter is given the result of the corresponding
@scheme[_value-expr]. When control leaves the @racket[parameterize]
form---either through a normal return, an exception, or some other
escape---the parameter reverts to its earlier value:
@interaction[
#:eval param-eval
(parameterize ([location "there"])
(location))
(location)
(parameterize ([location "in a house"])
(list (location)
(parameterize ([location "with a mouse"])
(location))
(location)))
(parameterize ([location "in a box"])
(car (location)))
(location)
]
The @scheme[parameterize] form is not a binding form like
@scheme[let]; each use of @racket[location] above refers directly to
the original definition. A @scheme[parameterize] form adjusts the
value of a parameter during the whole time that the
@scheme[parameterize] body is evaluated, even for uses of the
parameter that are textually outside of the @racket[parameterize]
body:
@interaction[
#:eval param-eval
(define (would-you-could-you?)
(and (not (equal? (location) "here"))
(not (equal? (location) "there"))))
(would-you-could-you?)
(parameterize ([location "on a bus"])
(would-you-could-you?))
]
If a use of a parameter is textually inside the body of a
@racket[parameterize] but not evaluated before the
@racket[parameterize] form produces a value, then the use does not see
the value installed by the @racket[parameterize] form:
@interaction[
#:eval param-eval
(let ([get (parameterize ([location "with a fox"])
(lambda () (location)))])
(get))
]
The current binding of a parameter can be adjusted imperatively by
calling the parameter as a function with a value. If a
@racket[parameterize] has adjusted the value of the parameter, then
directly applying the parameter procedure affects only the value
associated with the active @racket[parameterize]:
@interaction[
#:eval param-eval
(define (try-again! where)
(location where))
(location)
(parameterize ([location "on a train"])
(list (location)
(begin (try-again! "in a boat")
(location))))
(location)
]
Using @racket[parameterize] is generally preferable to updating a
parameter value imperatively---for much the same reasons that binding
a fresh variable with @scheme[let] is preferable to using
@scheme[set!] (see @secref["set!"]).
It may seem that variables and @racket[set!] can solve many of the
same problems that parameters solve. For example, @racket[lokation]
could be defined as a string, and @racket[set!] could be used
to adjust its value:
@interaction[
#:eval param-eval
(define lokation "here")
(define (would-ya-could-ya?)
(and (not (equal? lokation "here"))
(not (equal? lokation "there"))))
(set! location "on a bus")
(would-ya-could-ya?)
]
Parameters, however, offer several crucial advantages over
@scheme[set!]:
@itemlist[
@item{The @racket[parameterize] form helps automatically reset the
value of a parameter when control escapes due to an exception.
Adding exception handlers and other forms to rewind a
@scheme[set!] is relatively tedious.}
@item{Parameters work nicely with tail calls (see
@secref["tail-recursion"]). The last @racket[_body] in a
@racket[parameterize] form is in @tech{tail position} with
respect to the @racket[parameterize] form.}
@item{Parameters work properly with threads (see
@refsecref["threads"]). The @scheme[parameterize] form adjusts
the value of a parameter only for evaluation in the current
thread, which avoids race conditions with other threads.}
]
@; ----------------------------------------
@close-eval[param-eval]

View File

@ -3,41 +3,43 @@
scribble/eval
"guide-utils.ss")
@(define qq (scheme quasiquote))
@(define uq (scheme unquote))
@(define qq (racket quasiquote))
@(define uq (racket unquote))
@title{Quasiquoting: @scheme[quasiquote] and @schemevalfont{`}}
@title[#:tag "qq"]{Quasiquoting: @racket[quasiquote] and @racketvalfont{`}}
The @scheme[quasiquote] form is similar to @scheme[quote]:
@refalso["quasiquote"]{@racket[quasiquote]}
The @racket[quasiquote] form is similar to @racket[quote]:
@specform[(#,qq datum)]
However, for each @scheme[(#,uq _expr)]
that appears within the @scheme[_datum], the @scheme[_expr] is
However, for each @racket[(#,uq _expr)]
that appears within the @racket[_datum], the @racket[_expr] is
evaluated to produce a value that takes the place of the
@scheme[unquote] sub-form.
@racket[unquote] sub-form.
@examples[
(eval:alts (#,qq (1 2 (#,uq (+ 1 2)) (#,uq (- 5 1))))
`(1 2 ,(+ 1 2), (- 5 1)))
]
The @scheme[unquote-splicing] form is similar to @scheme[unquote], but
its @scheme[_expr] must produce a list, and the
@scheme[unquote-splicing] form must appear in a context that produces
The @racket[unquote-splicing] form is similar to @racket[unquote], but
its @racket[_expr] must produce a list, and the
@racket[unquote-splicing] form must appear in a context that produces
either a list or a vector. As the name suggests, the resulting list
is spliced into the context of its use.
@examples[
(eval:alts (#,qq (1 2 (#,(scheme unquote-splicing) (list (+ 1 2) (- 5 1))) 5))
(eval:alts (#,qq (1 2 (#,(racket unquote-splicing) (list (+ 1 2) (- 5 1))) 5))
`(1 2 ,@(list (+ 1 2) (- 5 1)) 5))
]
If a @scheme[quasiquote] form appears within an enclosing
@scheme[quasiquote] form, then the inner @scheme[quasiquote]
effectively cancels one layer of @scheme[unquote] and
@scheme[unquote-splicing] forms, so that a second @scheme[unquote]
or @scheme[unquote-splicing] is needed.
If a @racket[quasiquote] form appears within an enclosing
@racket[quasiquote] form, then the inner @racket[quasiquote]
effectively cancels one layer of @racket[unquote] and
@racket[unquote-splicing] forms, so that a second @racket[unquote]
or @racket[unquote-splicing] is needed.
@examples[
(eval:alts (#,qq (1 2 (#,qq (#,uq (+ 1 2)
@ -48,7 +50,7 @@ or @scheme[unquote-splicing] is needed.
]
The evaluation above will not actually print as shown. Instead, the
shorthand form of @scheme[quasiquote] and @scheme[unquote] will be
shorthand form of @racket[quasiquote] and @racket[unquote] will be
used: @litchar{`} (i.e., a backquote) and @litchar{,} (i.e., a comma).
The same shorthands can be used in expressions:
@ -56,7 +58,7 @@ The same shorthands can be used in expressions:
`(1 2 `(,(+ 1 2) ,,(- 5 1)))
]
The shorthand for of @scheme[unquote-splicing] is @litchar[",@"]:
The shorthand for of @racket[unquote-splicing] is @litchar[",@"]:
@examples[
`(1 2 ,@(list (+ 1 2) (- 5 1)))

View File

@ -3,63 +3,61 @@
scribble/eval
"guide-utils.ss")
@title[#:tag "quote"]{Quoting: @scheme[quote] and @schemevalfont{'}}
@title[#:tag "quote"]{Quoting: @racket[quote] and @racketvalfont{'}}
@refalso["quote"]{@scheme[quote]}
@refalso["quote"]{@racket[quote]}
The @scheme[quote] form produces a constant:
The @racket[quote] form produces a constant:
@specform[(#,(schemekeywordfont "quote") datum)]
@specform[(#,(racketkeywordfont "quote") datum)]
The syntax of a @scheme[datum] is technically specified as anything
that the @scheme[read] function parses as a single element. The value
of the @scheme[quote] form is the same value that @scheme[read] would
produce given @scheme[_datum].
The syntax of a @racket[datum] is technically specified as anything
that the @racket[read] function parses as a single element. The value
of the @racket[quote] form is the same value that @racket[read] would
produce given @racket[_datum].
To a good approximation, the resulting value is such that
@scheme[_datum] is the value's printed representation. Thus, it can be
a symbol, a boolean, a number, a (character or byte) string, a
character, a keyword, an empty list, a pair (or list) containing more
such values, a vector containing more such values, a hash table
containing more such values, or a box containing another such value.
The @racket[_datum] can be a symbol, a boolean, a number, a (character
or byte) string, a character, a keyword, an empty list, a pair (or
list) containing more such values, a vector containing more such
values, a hash table containing more such values, or a box containing
another such value.
@examples[
(eval:alts (#,(schemekeywordfont "quote") apple) 'apple)
(eval:alts (#,(schemekeywordfont "quote") #t) #t)
(eval:alts (#,(schemekeywordfont "quote") 42) 42)
(eval:alts (#,(schemekeywordfont "quote") "hello") "hello")
(eval:alts (#,(schemekeywordfont "quote") ()) '())
(eval:alts (#,(schemekeywordfont "quote") ((1 2 3) #2("z" x) . the-end)) '((1 2 3) #2("z" x) . the-end))
(eval:alts (#,(schemekeywordfont "quote") (1 2 #,(schemeparenfont ".") (3))) '(1 2 . (3)))
(eval:alts (#,(racketkeywordfont "quote") apple) 'apple)
(eval:alts (#,(racketkeywordfont "quote") #t) #t)
(eval:alts (#,(racketkeywordfont "quote") 42) 42)
(eval:alts (#,(racketkeywordfont "quote") "hello") "hello")
(eval:alts (#,(racketkeywordfont "quote") ()) '())
(eval:alts (#,(racketkeywordfont "quote") ((1 2 3) #2("z" x) . the-end)) '((1 2 3) #2("z" x) . the-end))
(eval:alts (#,(racketkeywordfont "quote") (1 2 #,(racketparenfont ".") (3))) '(1 2 . (3)))
]
As the last example above shows, the @scheme[_datum] does not have to
be the normalized printed form of a value. A
@scheme[_datum] cannot be a printed representation that starts with
@litchar{#<}, however, so it cannot be @|void-const|,
@|undefined-const|, or a procedure.
As the last example above shows, the @racket[_datum] does not have to
match the normalized printed form of a value. A @racket[_datum] cannot
be a printed representation that starts with @litchar{#<}, so it
cannot be @|void-const|, @|undefined-const|, or a procedure.
The @scheme[quote] form is rarely used for a @scheme[_datum] that is a
The @racket[quote] form is rarely used for a @racket[_datum] that is a
boolean, number, or string by itself, since the printed forms of those
values can already be used as constants. The @scheme[quote] form is
values can already be used as constants. The @racket[quote] form is
more typically used for symbols and lists, which have other meanings
(identifiers, function calls, etc.) when not quoted.
An expression
@specform[(quote @#,schemevarfont{datum})]
@specform[(quote @#,racketvarfont{datum})]
is a shorthand for
@schemeblock[
(#,(schemekeywordfont "quote") #,(scheme _datum))
@racketblock[
(#,(racketkeywordfont "quote") #,(racket _datum))
]
and this shorthand is almost always used instead of
@scheme[quote]. The shorthand applies even within the @scheme[_datum],
so it can produce a list containing @scheme[quote].
@racket[quote]. The shorthand applies even within the @racket[_datum],
so it can produce a list containing @racket[quote].
@refdetails["parse-quote"]{the @schemevalfont{'} shorthand}
@refdetails["parse-quote"]{the @racketvalfont{'} shorthand}
@examples[
'apple

View File

@ -5,17 +5,17 @@
@(interaction-eval (require (lib "mzlib/for.ss")))
@title[#:tag "set!"]{Assignment: @scheme[set!]}
@title[#:tag "set!"]{Assignment: @racket[set!]}
@refalso["set!"]{@scheme[set!]}
@refalso["set!"]{@racket[set!]}
Assign to a variable using @scheme[set!]:
Assign to a variable using @racket[set!]:
@specform[(set! id expr)]
A @scheme[set!] expression evaluates @scheme[_expr] and changes
@scheme[_id] (which must be bound in the enclosing environment) to the
resulting value. The result of the @scheme[set!] expression itself is
A @racket[set!] expression evaluates @racket[_expr] and changes
@racket[_id] (which must be bound in the enclosing environment) to the
resulting value. The result of the @racket[set!] expression itself is
@|void-const|.
@defexamples[
@ -47,9 +47,9 @@ greeted
@;------------------------------------------------------------------------
@section[#:tag "using-set!"]{Guidelines for Using Assignment}
Although using @scheme[set!] is sometimes appropriate, Scheme style
generally discourages the use of @scheme[set!]. The following
guidelines may help explain when using @scheme[set!] is appropriate.
Although using @racket[set!] is sometimes appropriate, Racket style
generally discourages the use of @racket[set!]. The following
guidelines may help explain when using @racket[set!] is appropriate.
@itemize[
@ -136,7 +136,7 @@ guidelines may help explain when using @scheme[set!] is appropriate.
]] }
@item{For cases where stateful objects are necessary or appropriate,
then implementing the object's state with @scheme[set!] is
then implementing the object's state with @racket[set!] is
fine.
@as-examples[@t{Ok example:}
@ -159,24 +159,24 @@ resulting code is significantly more readable or if it implements a
significantly better algorithm.
The use of mutable values, such as vectors and hash tables, raises
fewer suspicions about the style of a program than using @scheme[set!]
directly. Nevertheless, simply replacing @scheme[set!]s in a program
with a @scheme[vector-set!]s obviously does not improve the style of
fewer suspicions about the style of a program than using @racket[set!]
directly. Nevertheless, simply replacing @racket[set!]s in a program
with a @racket[vector-set!]s obviously does not improve the style of
the program.
@;------------------------------------------------------------------------
@section{Multiple Values: @scheme[set!-values]}
@section{Multiple Values: @racket[set!-values]}
@refalso["set!"]{@scheme[set!-values]}
@refalso["set!"]{@racket[set!-values]}
The @scheme[set!-values] form assigns to multiple variables at once,
The @racket[set!-values] form assigns to multiple variables at once,
given an expression that produces an appropriate number of values:
@specform[(set!-values (id ...) expr)]
This form is equivalent to using @scheme[let-values] to receive
multiple results from @scheme[_expr], and then assigning the results
individually to the @scheme[_id]s using @scheme[set!].
This form is equivalent to using @racket[let-values] to receive
multiple results from @racket[_expr], and then assigning the results
individually to the @racket[_id]s using @racket[set!].
@defexamples[
(define game

View File

@ -5,8 +5,8 @@
@title{Simple Values}
Scheme values include numbers, booleans, strings, and byte strings. In
DrScheme and documentation examples (when you read the documentation
Racket values include numbers, booleans, strings, and byte strings. In
DrRacket and documentation examples (when you read the documentation
in color), value expressions are shown in green.
@defterm{Numbers} are written in the usual way, including fractions
@ -14,14 +14,14 @@ and imaginary numbers:
@moreguide["numbers"]{numbers}
@schemeblock[
@racketblock[
1 3.14
1/2 6.02e+23
1+2i 9999999999999999999999
]
@defterm{Booleans} are @scheme[#t] for true and @scheme[#f] for
false. In conditionals, however, all non-@scheme[#f] values are
@defterm{Booleans} are @racket[#t] for true and @racket[#f] for
false. In conditionals, however, all non-@racket[#f] values are
treated as true.
@moreguide["booleans"]{booleans}
@ -34,7 +34,7 @@ appear in a string constant.
@moreguide["strings"]{strings}
@schemeblock[
@racketblock[
"Hello, world!"
"Benjamin \"Bugsy\" Siegel"
"\u03BBx:(\u03BC\u03B1.\u03B1\u2192\u03B1).xx"
@ -42,11 +42,11 @@ appear in a string constant.
When a constant is evaluated in the @tech{REPL}, it typically prints the same
as its input syntax. In some cases, the printed form is a normalized
version of the input syntax. In documentation and in DrScheme's @tech{REPL},
version of the input syntax. In documentation and in DrRacket's @tech{REPL},
results are printed in blue instead of green to highlight the
difference between an input expression and a printed result.
@examples[
(eval:alts (unsyntax (schemevalfont "1.0000")) 1.0000)
(eval:alts (unsyntax (schemevalfont "\"Bugs \\u0022Figaro\\u0022 Bunny\"")) "Bugs \u0022Figaro\u0022 Bunny")
(eval:alts (unsyntax (racketvalfont "1.0000")) 1.0000)
(eval:alts (unsyntax (racketvalfont "\"Bugs \\u0022Figaro\\u0022 Bunny\"")) "Bugs \u0022Figaro\u0022 Bunny")
]

View File

@ -10,7 +10,7 @@
A program module is written as
@schemeblock[
@racketblock[
@#,BNF-seq[@litchar{#lang} @nonterm{langname} @kleenestar{@nonterm{topform}}]
]
@ -67,11 +67,11 @@ A definition of the form
@moreguide["define"]{definitions}
@schemeblock[@#,val-defn-stx]
@racketblock[@#,val-defn-stx]
binds @nonterm{id} to the result of @nonterm{expr}, while
@schemeblock[@#,fun-defn-stx]
@racketblock[@#,fun-defn-stx]
binds the first @nonterm{id} to a function (also called a
@defterm{procedure}) that takes arguments as named by the remaining
@ -81,8 +81,8 @@ the last @nonterm{expr}.
@defexamples[
#:eval ex-eval
(code:line (define pie 3) (code:comment @#,t{defines @scheme[pie] to be @scheme[3]}))
(code:line (define (piece str) (code:comment @#,t{defines @scheme[piece] as a function})
(code:line (define pie 3) (code:comment @#,t{defines @racket[pie] to be @racket[3]}))
(code:line (define (piece str) (code:comment @#,t{defines @racket[piece] as a function})
(substring str 0 pie)) (code:comment @#,t{ of one argument}))
pie
(piece "key lime")
@ -113,11 +113,11 @@ evaluated only for some side-effect, such as printing.
(bake "apple")
]
Scheme programmers prefer to avoid side-effects, so a definition usually
Racket programmers prefer to avoid side-effects, so a definition usually
has just one expression in its body. It's
important, though, to understand that multiple expressions are allowed
in a definition body, because it explains why the following
@scheme[nobake] function simply returns its argument:
@racket[nobake] function simply returns its argument:
@def+int[
#:eval ex-eval
@ -126,53 +126,53 @@ in a definition body, because it explains why the following
(nobake "green")
]
Within @scheme[nobake], there are no parentheses around
@scheme[string-append flavor "jello"], so they are three separate
Within @racket[nobake], there are no parentheses around
@racket[string-append flavor "jello"], so they are three separate
expressions instead of one function-call expression. The expressions
@scheme[string-append] and @scheme[flavor] are evaluated, but the
@racket[string-append] and @racket[flavor] are evaluated, but the
results are never used. Instead, the result of the function is just
the result of the final expression, @scheme["jello"].
the result of the final expression, @racket["jello"].
@; ----------------------------------------------------------------------
@section[#:tag "indentation"]{An Aside on Indenting Code}
Line breaks and indentation are not significant for parsing Scheme
programs, but most Scheme programmers use a standard set of conventions
Line breaks and indentation are not significant for parsing Racket
programs, but most Racket programmers use a standard set of conventions
to make code more readable. For example, the body of a definition is
typically indented under the first line of the definition. Identifiers
are written immediately after an open parenthesis with no extra space,
and closing parentheses never go on their own line.
DrScheme automatically indents according to the standard style when
DrRacket automatically indents according to the standard style when
you type Enter in a program or @tech{REPL} expression. For example, if you
hit Enter after typing @litchar{(define (greet name)}, then DrScheme
hit Enter after typing @litchar{(define (greet name)}, then DrRacket
automatically inserts two spaces for the next line. If you change a
region of code, you can select it in DrScheme and hit Tab, and
DrScheme will re-indent the code (without inserting any line breaks).
Editors like Emacs offer a Scheme mode with similar indentation
region of code, you can select it in DrRacket and hit Tab, and
DrRacket will re-indent the code (without inserting any line breaks).
Editors like Emacs offer a Racket or Scheme mode with similar indentation
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
extra feedback that your parentheses match in the way that you
intended. For example, if you leave out a closing parenthesis after
the last argument to a function, automatic indentation starts the
next line under the first argument, instead of under the
@scheme[define] keyword:
@racket[define] keyword:
@schemeblock[
@racketblock[
(define (halfbake flavor
(string-append flavor " creme brulee")))
]
In this case, indentation helps highlight the mistake. In other cases,
where the indentation may be normal while an open parenthesis has no
matching close parenthesis, both @exec{mzscheme} and DrScheme use the
matching close parenthesis, both @exec{racket} and DrRacket use the
source's indentation to suggest where a parenthesis might be missing.
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@section{Identifiers}
Scheme's syntax for identifiers is especially liberal. Excluding the
Racket's syntax for identifiers is especially liberal. Excluding the
special characters
@moreguide["binding"]{identifiers}
@ -186,41 +186,41 @@ special characters
and except for the sequences of characters that make number constants,
almost any sequence of non-whitespace characters forms an
@nonterm{id}. For example @schemeid[substring] is an
identifier. Also, @schemeid[string-append] and @schemeid[a+b] are
@nonterm{id}. For example @racketid[substring] is an
identifier. Also, @racketid[string-append] and @racketid[a+b] are
identifiers, as opposed to arithmetic expressions. Here are several
more examples:
@schemeblock[
@#,schemeid[+]
@#,schemeid[Hfuhruhurr]
@#,schemeid[integer?]
@#,schemeid[pass/fail]
@#,schemeid[john-jacob-jingleheimer-schmidt]
@#,schemeid[a-b-c+1-2-3]
@racketblock[
@#,racketid[+]
@#,racketid[Hfuhruhurr]
@#,racketid[integer?]
@#,racketid[pass/fail]
@#,racketid[john-jacob-jingleheimer-schmidt]
@#,racketid[a-b-c+1-2-3]
]
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@section{Function Calls@aux-elem{ (Procedure Applications)}}
We have already seen many function calls, which are called
@defterm{procedure applications} in more traditional Scheme
@defterm{procedure applications} in more traditional
terminology. The syntax of a function call is
@moreguide["application"]{function calls}
@schemeblock[
@racketblock[
#,app-expr-stx
]
where the number of @nonterm{expr}s determines the number of
arguments supplied to the function named by @nonterm{id}.
The @schememodname[scheme] language pre-defines many function
identifiers, such as @scheme[substring] and
@scheme[string-append]. More examples are below.
The @racketmodname[racket] language pre-defines many function
identifiers, such as @racket[substring] and
@racket[string-append]. More examples are below.
In example Scheme code throughout the documentation, uses of
In example Racket code throughout the documentation, uses of
pre-defined names are hyperlinked to the reference manual. So, you can
click on an identifier to get full details about its use.
@ -244,19 +244,19 @@ click on an identifier to get full details about its use.
]
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@section{Conditionals with @scheme[if], @scheme[and], @scheme[or], and @scheme[cond]}
@section{Conditionals with @racket[if], @racket[and], @racket[or], and @racket[cond]}
The next simplest kind of expression is an @scheme[if] conditional:
The next simplest kind of expression is an @racket[if] conditional:
@schemeblock[
@racketblock[
#,if-expr-stx
]
@moreguide["conditionals"]{conditionals}
The first @nonterm{expr} is always evaluated. If it produces a
non-@scheme[#f] value, then the second @nonterm{expr} is
evaluated for the result of the whole @scheme[if] expression, otherwise
non-@racket[#f] value, then the second @nonterm{expr} is
evaluated for the result of the whole @racket[if] expression, otherwise
the third @nonterm{expr} is evaluated for the result.
@examples[
@ -270,15 +270,15 @@ the third @nonterm{expr} is evaluated for the result.
(if (equal? "hello" (substring s 0 5))
"hi!"
"huh?"))
(reply "hello scheme")
(reply "hello racket")
(reply "\u03BBx:(\u03BC\u03B1.\u03B1\u2192\u03B1).xx")
]
Complex conditionals can be formed by nesting @scheme[if]
expressions. For example, you could make the @scheme[reply] function
Complex conditionals can be formed by nesting @racket[if]
expressions. For example, you could make the @racket[reply] function
work when given non-strings:
@schemeblock[
@racketblock[
(define (reply s)
(if (string? s)
(if (equal? "hello" (substring s 0 5))
@ -287,10 +287,10 @@ work when given non-strings:
"huh?"))
]
Instead of duplicating the @scheme["huh?"] case, this function is
Instead of duplicating the @racket["huh?"] case, this function is
better written as
@schemeblock[
@racketblock[
(define (reply s)
(if (if (string? s)
(equal? "hello" (substring s 0 5))
@ -299,20 +299,20 @@ better written as
"huh?"))
]
but these kinds of nested @scheme[if]s are difficult to read. Scheme
provides more readable shortcuts through the @scheme[and] and
@scheme[or] forms, which work with any number of expressions:
but these kinds of nested @racket[if]s are difficult to read. Racket
provides more readable shortcuts through the @racket[and] and
@racket[or] forms, which work with any number of expressions:
@moreguide["and+or"]{@scheme[and] and @scheme[or]}
@moreguide["and+or"]{@racket[and] and @racket[or]}
@schemeblock[
@racketblock[
#,and-expr-stx
#,or-expr-stx
]
The @scheme[and] form short-circuits: it stops and returns @scheme[#f]
when an expression produces @scheme[#f], otherwise it keeps
going. The @scheme[or] form similarly short-circuits when it
The @racket[and] form short-circuits: it stops and returns @racket[#f]
when an expression produces @racket[#f], otherwise it keeps
going. The @racket[or] form similarly short-circuits when it
encounters a true result.
@defexamples[
@ -322,14 +322,14 @@ encounters a true result.
(equal? "hello" (substring s 0 5)))
"hi!"
"huh?"))
(reply "hello scheme")
(reply "hello racket")
(reply 17)
]
Another common pattern of nested @scheme[if]s involves a sequence of
Another common pattern of nested @racket[if]s involves a sequence of
tests, each with its own result:
@schemeblock[
@racketblock[
(define (reply-more s)
(if (equal? "hello" (substring s 0 5))
"hi!"
@ -340,25 +340,25 @@ tests, each with its own result:
"huh?"))))
]
The shorthand for a sequence of tests is the @scheme[cond] form:
The shorthand for a sequence of tests is the @racket[cond] form:
@moreguide["cond"]{@scheme[cond]}
@moreguide["cond"]{@racket[cond]}
@schemeblock[
@racketblock[
#,cond-expr-stx
]
A @scheme[cond] form contains a sequence of clauses between square
A @racket[cond] form contains a sequence of clauses between square
brackets. In each clause, the first @nonterm{expr} is a test
expression. If it produces true, then the clause's remaining
@nonterm{expr}s are evaluated, and the last one in the clause provides
the answer for the entire @scheme[cond] expression; the rest of the
clauses are ignored. If the test @nonterm{expr} produces @scheme[#f],
the answer for the entire @racket[cond] expression; the rest of the
clauses are ignored. If the test @nonterm{expr} produces @racket[#f],
then the clause's remaining @nonterm{expr}s are ignored, and
evaluation continues with the next clause. The last clause can use
@scheme[else] as a synonym for a @scheme[#t] test expression.
@racket[else] as a synonym for a @racket[#t] test expression.
Using @scheme[cond], the @scheme[reply-more] function can be more
Using @racket[cond], the @racket[reply-more] function can be more
clearly written as follows:
@def+int[
@ -371,17 +371,17 @@ clearly written as follows:
[(equal? "?" (substring s (- (string-length s) 1)))
"I don't know"]
[else "huh?"]))
(reply-more "hello scheme")
(reply-more "hello racket")
(reply-more "goodbye cruel world")
(reply-more "what is your favorite color?")
(reply-more "mine is lime green")
]
The use of square brackets for @scheme[cond] clauses is a
convention. In Scheme, parentheses and square brackets are actually
The use of square brackets for @racket[cond] clauses is a
convention. In Racket, parentheses and square brackets are actually
interchangable, as long as @litchar{(} is matched with @litchar{)} and
@litchar{[} is matched with @litchar{]}. Using square brackets in a
few key places makes Scheme code even more readable.
few key places makes Racket code even more readable.
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@section{Function Calls, Again}
@ -392,12 +392,12 @@ expression for the function, instead of just an @nonterm{id}:
@moreguide["application"]{function calls}
@schemeblock[
@racketblock[
#,app2-expr-stx
]
The first @nonterm{expr} is often an @nonterm{id}, such
as @scheme[string-append] or @scheme[+], but it can be anything that
as @racket[string-append] or @racket[+], but it can be anything that
evaluates to a function. For example, it can be a conditional
expression:
@ -419,12 +419,12 @@ parentheses around an expression, you'll most often get an ``expected
a procedure'' error like this one.
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@section{Anonymous Functions with @scheme[lambda]}
@section{Anonymous Functions with @racket[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
Programming in Racket would be tedious if you had to name all of your
numbers. Instead of writing @racket[(+ 1 2)], you'd have to write
@moreguide["lambda"]{@scheme[lambda]}
@moreguide["lambda"]{@racket[lambda]}
@interaction[
(define a 1)
@ -433,9 +433,9 @@ numbers. Instead of writing @scheme[(+ 1 2)], you'd have to write
]
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]:
too. For example, you might have a function @racket[twice] that takes
a function and an argument. Using @racket[twice] is convenient if you
already have a name for the function, such as @racket[sqrt]:
@def+int[
#:eval ex-eval
@ -445,7 +445,7 @@ already have a name for the function, such as @scheme[sqrt]:
]
If you want to call a function that is not yet defined, you could
define it, and then pass it to @scheme[twice]:
define it, and then pass it to @racket[twice]:
@def+int[
#:eval ex-eval
@ -454,22 +454,22 @@ define it, and then pass it to @scheme[twice]:
(twice louder "hello")
]
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 function directly. The @scheme[lambda] form is followed by
But if the call to @racket[twice] is the only place where
@racket[louder] is used, it's a shame to have to write a whole
definition. In Racket, you can use a @racket[lambda] expression to
produce a function directly. The @racket[lambda] form is followed by
identifiers for the function's arguments, and then the function's
body expressions:
@schemeblock[
@racketblock[
#,lambda-expr-stx
]
Evaluating a @scheme[lambda] form by itself produces a function:
Evaluating a @racket[lambda] form by itself produces a function:
@interaction[(lambda (s) (string-append s "!"))]
Using @scheme[lambda], the above call to @scheme[twice] can be
Using @racket[lambda], the above call to @racket[twice] can be
re-written as
@interaction[
@ -480,7 +480,7 @@ re-written as
"hello")
]
Another use of @scheme[lambda] is as a result for a function that
Another use of @racket[lambda] is as a result for a function that
generates functions:
@def+int[
@ -492,11 +492,11 @@ generates functions:
(twice (make-add-suffix "...") "hello")
]
Scheme is a @defterm{lexically scoped} language, which means that
@scheme[s2] in the function returned by @scheme[make-add-suffix]
Racket is a @defterm{lexically scoped} language, which means that
@racket[s2] in the function returned by @racket[make-add-suffix]
always refers to the argument for the call that created the
function. In other words, the @scheme[lambda]-generated function
``remembers'' the right @scheme[s2]:
function. In other words, the @racket[lambda]-generated function
``remembers'' the right @racket[s2]:
@interaction[
#:eval ex-eval
@ -506,12 +506,12 @@ function. In other words, the @scheme[lambda]-generated function
(twice louder "really")
]
We have so far referred to definitions of the form @scheme[(define
We have so far referred to definitions of the form @racket[(define
@#,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
@nonterm{expr} could be a @racket[lambda] form, in which case
the definition is equivalent to using the ``function'' definition
form. For example, the following two definitions of @scheme[louder]
form. For example, the following two definitions of @racket[louder]
are equivalent:
@defs+int[
@ -525,22 +525,22 @@ are equivalent:
louder
]
Note that the expression for @scheme[louder] in the second case is an
``anonymous'' function written with @scheme[lambda], but, if
Note that the expression for @racket[louder] in the second case is an
``anonymous'' function written with @racket[lambda], but, if
possible, the compiler infers a name, anyway, to make printing and
error reporting as informative as possible.
@;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@section[#:tag "local-binding-intro"]{Local Binding with
@scheme[define], @scheme[let], and @scheme[let*]}
@racket[define], @racket[let], and @racket[let*]}
It's time to retract another simplification in our grammar of
Scheme. In the body of a function, definitions can appear before the
Racket. In the body of a function, definitions can appear before the
body expressions:
@moreguide["intdefs"]{local (internal) definitions}
@schemeblock[
@racketblock[
#,fun-defn2-stx
#,lambda2-expr-stx
]
@ -550,8 +550,8 @@ function body.
@defexamples[
(define (converse s)
(define (starts? s2) (code:comment @#,t{local to @scheme[converse]})
(define len2 (string-length s2)) (code:comment @#,t{local to @scheme[starts?]})
(define (starts? s2) (code:comment @#,t{local to @racket[converse]})
(define len2 (string-length s2)) (code:comment @#,t{local to @racket[starts?]})
(and (>= (string-length s) len2)
(equal? s2 (substring s 0 len2))))
(cond
@ -560,24 +560,24 @@ function body.
[else "huh?"]))
(converse "hello!")
(converse "urp")
(eval:alts (code:line starts? (code:comment @#,t{outside of @scheme[converse], so...}))
(eval:alts (code:line starts? (code:comment @#,t{outside of @racket[converse], so...}))
(parameterize ([current-namespace (make-base-namespace)]) (eval 'starts?)))
]
Another way to create local bindings is the @scheme[let] form. An
advantage of @scheme[let] is that it can be used in any expression
position. Also, @scheme[let] binds many identifiers at once, instead
of requiring a separate @scheme[define] for each identifier.
Another way to create local bindings is the @racket[let] form. An
advantage of @racket[let] is that it can be used in any expression
position. Also, @racket[let] binds many identifiers at once, instead
of requiring a separate @racket[define] for each identifier.
@moreguide["intdefs"]{@scheme[let] and @scheme[let*]}
@moreguide["intdefs"]{@racket[let] and @racket[let*]}
@schemeblock[
@racketblock[
#,let-expr-stx
]
Each binding clause is an @nonterm{id} and a
@nonterm{expr} surrounded by square brackets, and the
expressions after the clauses are the body of the @scheme[let]. In
expressions after the clauses are the body of the @racket[let]. In
each clause, the @nonterm{id} is bound to the result of the
@nonterm{expr} for use in the body.
@ -590,9 +590,9 @@ each clause, the @nonterm{id} is bound to the result of the
[else "cat's game"]))
]
The bindings of a @scheme[let] form are available only in the body of
the @scheme[let], so the binding clauses cannot refer to each
other. The @scheme[let*] form, in contrast, allows later clauses to
The bindings of a @racket[let] form are available only in the body of
the @racket[let], so the binding clauses cannot refer to each
other. The @racket[let*] form, in contrast, allows later clauses to
use earlier bindings:
@interaction[

View File

@ -5,9 +5,9 @@
@title[#:tag "symbols"]{Symbols}
A @deftech{symbol} is an atomic value that prints like an identifier.
An expression that starts with @litchar{'} and continues with an
identifier produces a symbol value.
A @deftech{symbol} is an atomic value that prints like an identifier
preceded with @litchar{'}. An expression that starts with @litchar{'}
and continues with an identifier produces a symbol value.
@examples[
'a
@ -15,13 +15,13 @@ identifier produces a symbol value.
]
For any sequence of characters, exactly one corresponding symbol is
@defterm{interned}; calling the @scheme[string->symbol] procedure, or
@scheme[read]ing a syntactic identifier, produces an interned
@defterm{interned}; calling the @racket[string->symbol] procedure, or
@racket[read]ing a syntactic identifier, produces an interned
symbol. Since interned symbols can be cheaply compared with
@scheme[eq?] (and thus @scheme[eqv?] or @scheme[equal?]), they serves
@racket[eq?] (and thus @racket[eqv?] or @racket[equal?]), they serves
as a convenient values to use for tags and enumerations.
Symbols are case-sensitive. By using a @schemefont{#ci} prefix or in
Symbols are case-sensitive. By using a @racketfont{#ci} prefix or in
other ways, the reader can be made to case-fold character sequences to
arrive at a symbol, but the reader preserves case by default.
@ -30,11 +30,11 @@ arrive at a symbol, but the reader preserves case by default.
(eq? 'a (string->symbol "a"))
(eq? 'a 'b)
(eq? 'a 'A)
(eval:alts @#,elem{@schemefont{#ci}@schemevalfont{'A}} #ci'A)
(eval:alts @#,elem{@racketfont{#ci}@racketvalfont{'A}} #ci'A)
]
Any string (i.e., any character sequence) can be supplied to
@scheme[string->symbol] to obtain the corresponding symbol. For reader
@racket[string->symbol] to obtain the corresponding symbol. For reader
input, any character can appear directly in an identifier, except for
whitespace and the following special characters:
@ -61,7 +61,7 @@ special characters or that might otherwise look like numbers.
@refdetails/gory["parse-symbol"]{the syntax of symbols}
The @scheme[display] form of a symbol is the same as the corresponding
The @racket[display] form of a symbol is the same as the corresponding
string.
@examples[
@ -69,9 +69,9 @@ string.
(display '|6|)
]
The @scheme[gensym] and @scheme[string->uninterned-symbol] procedures
The @racket[gensym] and @racket[string->uninterned-symbol] procedures
generate fresh @defterm{uninterned} symbols that are not equal
(according to @scheme[eq?]) to any previously interned or uninterned
(according to @racket[eq?]) to any previously interned or uninterned
symbol. Uninterned symbols are useful as fresh tags that cannot be
confused with any other value.

View File

@ -3,10 +3,10 @@
scribble/eval
"guide-utils.ss")
@title[#:tag "to-scheme" #:style 'toc]{Scheme Essentials}
@title[#:tag "to-scheme" #:style 'toc]{Racket Essentials}
This chapter provides a quick introduction to Scheme as background for
the rest of the guide. Readers with some Scheme experience can safely
This chapter provides a quick introduction to Racket as background for
the rest of the guide. Readers with some Racket experience can safely
skip to @secref["datatypes"].
@local-table-of-contents[]

View File

@ -1,35 +1,36 @@
#lang scribble/doc
@(require scribble/manual
scribble/eval
scheme/list
racket/list
"guide-utils.ss"
(for-label scheme/list))
(for-label racket/list
(only-in racket/class is-a?)))
@(define list-eval (make-base-eval))
@(interaction-eval #:eval list-eval (require scheme/list))
@(interaction-eval #:eval list-eval (require racket/list))
@title{Pairs, Lists, and Scheme Syntax}
@title{Pairs, Lists, and Racket Syntax}
The @scheme[cons] function actually accepts any two values, not just
The @racket[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
@racket[empty] and not itself produced by @racket[cons], the result prints
in a special way. The two values joined with @racket[cons] are printed
between parentheses, but with a dot (i.e., a period surrounded by
whitespace) in between:
@interaction[(cons 1 2) (cons "banana" "split")]
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?] function is @scheme[pair?],
Thus, a value produced by @racket[cons] is not always a list. In
general, the result of @racket[cons] is a @defterm{pair}. The more
traditional name for the @racket[cons?] function is @racket[pair?],
and we'll use the traditional name from now on.
The name @scheme[rest] also makes less sense for non-list pairs; the
more traditional names for @scheme[first] and @scheme[rest] are
@scheme[car] and @scheme[cdr], respectively. (Granted, the traditional
The name @racket[rest] also makes less sense for non-list pairs; the
more traditional names for @racket[first] and @racket[rest] are
@racket[car] and @racket[cdr], respectively. (Granted, the traditional
names are also nonsense. Just remember that ``a'' comes before ``d,''
and @scheme[cdr] is pronounced ``could-er.'')
and @racket[cdr] is pronounced ``could-er.'')
@examples[
#:eval list-eval
@ -42,24 +43,24 @@ and @scheme[cdr] is pronounced ``could-er.'')
@close-eval[list-eval]
Scheme's pair datatype and its relation to lists is essentially a
Racket's pair datatype and its relation to lists is essentially a
historical curiosity, along with the dot notation for printing and the
funny names @scheme[car] and @scheme[cdr]. Pairs are deeply wired into
to the culture, specification, and implementation of Scheme, however,
funny names @racket[car] and @racket[cdr]. Pairs are deeply wired into
to the culture, specification, and implementation of Racket, however,
so they survive in the language.
You are perhaps most likely to encounter a non-list pair when making a
mistake, such as accidentally reversing the arguments to
@scheme[cons]:
@racket[cons]:
@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] function takes a list of pairs, where the
@scheme[car] of each pair is a key and the @scheme[cdr] is an
@racket[make-hash] function takes a list of pairs, where the
@racket[car] of each pair is a key and the @racket[cdr] is an
arbitrary value.
The only thing more confusing to new Schemers than non-list pairs is
The only thing more confusing to new Racketeers than non-list pairs is
the printing convention for pairs where the second element @italic{is}
a pair, but @italic{is not} a list:
@ -68,12 +69,12 @@ a pair, but @italic{is not} a list:
In general, the rule for printing a pair is as follows: use the dot
notation always, but if the dot is immediately followed by an open
parenthesis, then remove the dot, the open parenthesis, and the
matching close parenthesis. Thus, @schemeresultfont{(0 . (1 . 2))}
becomes @schemeresult[(0 1 . 2)], and
@schemeresultfont{(1 . (2 . (3 . ())))} becomes @schemeresult[(1 2 3)].
matching close parenthesis. Thus, @racketresultfont{`(0 . (1 . 2))}
becomes @racketresult[`(0 1 . 2)], and
@racketresultfont{`(1 . (2 . (3 . ())))} becomes @racketresult[`(1 2 3)].
@;------------------------------------------------------------------------
@section[#:tag "quoting-lists"]{Quoting Pairs and Symbols with @scheme[quote]}
@section[#:tag "quoting-lists"]{Quoting Pairs and Symbols with @racket[quote]}
After you see
@ -82,79 +83,86 @@ After you see
]
enough times, you'll wish (or you're already wishing) that there was a
way to write just @scheme[((1) (2) (3))] and have it mean the list of
lists that prints as @schemeresult[((1) (2) (3))]. The @scheme[quote]
way to write just @racket[((1) (2) (3))] and have it mean the list of
lists that prints as @racketresult[`((1) (2) (3))]. The @racket[quote]
form does exactly that:
@interaction[
(eval:alts (@#,scheme[quote] ((1) (2) (3))) '((1) (2) (3)))
(eval:alts (@#,scheme[quote] ("red" "green" "blue")) '("red" "green" "blue"))
(eval:alts (@#,scheme[quote] ()) '())
(eval:alts (@#,racket[quote] ((1) (2) (3))) '((1) (2) (3)))
(eval:alts (@#,racket[quote] ("red" "green" "blue")) '("red" "green" "blue"))
(eval:alts (@#,racket[quote] ()) '())
]
The @scheme[quote] form works with the dot notation, too, whether the
The @racket[quote] form works with the dot notation, too, whether the
quoted form is normalized by the dot-parenthesis elimination rule or
not:
@interaction[
(eval:alts (@#,scheme[quote] (1 . 2)) '(1 . 2))
(eval:alts (@#,scheme[quote] (0 @#,schemeparenfont{.} (1 . 2))) '(0 . (1 . 2)))
(eval:alts (@#,racket[quote] (1 . 2)) '(1 . 2))
(eval:alts (@#,racket[quote] (0 @#,racketparenfont{.} (1 . 2))) '(0 . (1 . 2)))
]
Naturally, lists of any kind can be nested:
@interaction[
(list (list 1 2 3) 5 (list "a" "b" "c"))
(eval:alts (@#,scheme[quote] ((1 2 3) 5 ("a" "b" "c"))) '((1 2 3) 5 ("a" "b" "c")))
(eval:alts (@#,racket[quote] ((1 2 3) 5 ("a" "b" "c"))) '((1 2 3) 5 ("a" "b" "c")))
]
If you wrap an identifier with @scheme[quote], then you get output
that looks like an identifier:
If you wrap an identifier with @racket[quote], then you get output
that looks like an identifier, but with a @litchar{'} prefix:
@interaction[
(eval:alts (@#,scheme[quote] jane-doe) 'jane-doe)
(eval:alts (@#,racket[quote] jane-doe) 'jane-doe)
]
A value that prints like an identifier is a @defterm{symbol}. In the
same way that parenthesized output should not be confused with
expressions, a printed symbol should not be confused with an
identifier. In particular, the symbol @scheme[(@#,scheme[quote]
@#,schemeidfont{map})] has nothing to do with the @schemeidfont{map}
identifier. In particular, the symbol @racket[(@#,racket[quote]
@#,racketidfont{map})] has nothing to do with the @racketidfont{map}
identifier or the predefined function that is bound to
@scheme[map], except that the symbol and the identifier happen
@racket[map], except that the symbol and the identifier happen
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 functions
@scheme[symbol->string] and @scheme[string->symbol] convert between
@racket[symbol->string] and @racket[string->symbol] convert between
them.
@examples[
map
(eval:alts (@#,scheme[quote] @#,schemeidfont{map}) 'map)
(eval:alts (symbol? (@#,scheme[quote] @#,schemeidfont{map})) (symbol? 'map))
(eval:alts (@#,racket[quote] @#,racketidfont{map}) 'map)
(eval:alts (symbol? (@#,racket[quote] @#,racketidfont{map})) (symbol? 'map))
(symbol? map)
(procedure? map)
(string->symbol "map")
(eval:alts (symbol->string (@#,scheme[quote] @#,schemeidfont{map})) (symbol->string 'map))
(eval:alts (symbol->string (@#,racket[quote] @#,racketidfont{map})) (symbol->string 'map))
]
When @scheme[quote] is used on a parenthesized sequence of
When @racket[quote] is used on a parenthesized sequence of
identifiers, it creates a list of symbols:
@interaction[
(eval:alts (@#,scheme[quote] (@#,schemeidfont{road} @#,schemeidfont{map})) '(road map))
(eval:alts (car (@#,scheme[quote] (@#,schemeidfont{road} @#,schemeidfont{map}))) (car '(road map)))
(eval:alts (symbol? (car (@#,scheme[quote] (@#,schemeidfont{road} @#,schemeidfont{map})))) (symbol? (car '(road map))))
(eval:alts (car (@#,racket[quote] (@#,racketidfont{road} @#,racketidfont{map}))) (car '(road map)))
(eval:alts (symbol? (car (@#,racket[quote] (@#,racketidfont{road} @#,racketidfont{map})))) (symbol? (car '(road map))))
]
When a symbol is inside a
list that is printed with @litchar{`}, the @litchar{'} on the symbol
is omitted, since @litchar{`} is doing the job already:
@interaction[
(eval:alts (@#,racket[quote] (@#,racketidfont{road} @#,racketidfont{map})) '(road map))
]
@;------------------------------------------------------------------------
@section{Abbreviating @scheme[quote] with @schemevalfont{'}}
@section{Abbreviating @racket[quote] with @racketvalfont{'}}
If @scheme[(@#,scheme[quote] (1 2 3))] still seems like too much
If @racket[(@#,racket[quote] (1 2 3))] still seems like too much
typing, you can abbreviate by just putting @litchar{'} in front of
@scheme[(1 2 3)]:
@racket[(1 2 3)]:
@interaction[
'(1 2 3)
@ -162,31 +170,30 @@ typing, you can abbreviate by just putting @litchar{'} in front of
'((1 2 3) road ("a" "b" "c"))
]
In the documentation, @litchar{'} is printed in green along with the
In the documentation, @litchar{'} within an expression is printed in green along with the
form after it, since the combination is an expression that is a
constant. In DrScheme, only the @litchar{'} is colored green. DrScheme
is more precisely correct, because the meaning of @scheme[quote] can
constant. In DrRacket, only the @litchar{'} is colored green. DrRacket
is more precisely correct, because the meaning of @racket[quote] can
vary depending on the context of an expression. In the documentation,
however, we routinely assume that standard bindings are in scope, and
so we paint quoted forms in green for extra clarity.
A @litchar{'} expands to a @scheme[quote] form in quite a literal
A @litchar{'} expands to a @racket[quote] form in quite a literal
way. You can see this if you put a @litchar{'} in front of a form that has a
@litchar{'}:
@interaction[
(eval:alts (car '(@#,schemevalfont{quote} @#,schemevalfont{road})) 'quote)
(eval:alts (car '(@#,racketvalfont{quote} @#,racketvalfont{road})) 'quote)
(car ''road)
]
Beware, however, that the @tech{REPL}'s printer recognizes the symbol
@schemeidfont{quote} when printing output, and then it uses
@schemeidfont{'} in the output:
@racketidfont{quote} when printing output, and then it uses
@racketidfont{'} in the output:
@interaction[
'road
''road
(eval:alts '(@#,schemevalfont{quote} @#,schemevalfont{road}) ''road)
(eval:alts (list (@#,racketvalfont{quote} (@#,racketvalfont{quote} @#,racketvalfont{road}))) '('road))
(list ''road)
]
@; FIXME:
@ -194,13 +201,48 @@ Beware, however, that the @tech{REPL}'s printer recognizes the symbol
@; different than what "list" creates
@;------------------------------------------------------------------------
@section[#:tag "lists-and-syntax"]{Lists and Scheme Syntax}
@section{Quasiquoting with @racketvalfont{`}}
At this point, you may wonder why a symbol that is written with
@litchar{'} prints back with @litchar{'}, while a list that is written
with @litchar{'} prints back with @litchar{`}:
@interaction[
'road
'(left right)
]
The @litchar{`} character is a shorthand for @racket[quasiquote] in
the same way that @litchar{'} is short for @racket[quote]. The
@racket[quasiquote] form is like @scheme[quote], except that the
content of a @scheme[quasiquote]d form can escape back to a Racket
expression using @racket[unquote], which is abbreviated @litchar{,}:
@moreguide["qq"]{@racket[quasiquote]}
@interaction[
`(1 ,(+ 1 1) "buckle my shoe")
]
The value printer in Racket uses @litchar{`} for a lists in case it
must escape to print certain kinds of values that cannot be written
directly under @scheme[quote]. For example, a source-location record
is created with the @racket[srcloc] function, and it prints like an
equivalent call to @racket[srcloc]:
@interaction[
(srcloc "file.rkt" 1 0 1 (+ 4 4))
(list 'here (srcloc "file.rkt" 1 0 1 8) 'there)
]
@;------------------------------------------------------------------------
@section[#:tag "lists-and-syntax"]{Lists and Racket Syntax}
Now that you know the truth about pairs and lists, and now that you've
seen @scheme[quote], you're ready to understand the main way in which
we have been simplifying Scheme's true syntax.
seen @racket[quote], you're ready to understand the main way in which
we have been simplifying Racket's true syntax.
The syntax of Scheme is not defined directly in terms of character
The syntax of Racket is not defined directly in terms of character
streams. Instead, the syntax is determined by two layers:
@itemize[
@ -223,13 +265,13 @@ One consequence of the read layer for expressions is that you can use
the dot notation in expressions that are not quoted forms:
@interaction[
(eval:alts (+ 1 . @#,scheme[(2)]) (+ 1 2))
(eval:alts (+ 1 . @#,racket[(2)]) (+ 1 2))
]
This works because @scheme[(+ 1 . @#,scheme[(2)])] is just another
way of writing @scheme[(+ 1 2)]. It is practically never a good idea
This works because @racket[(+ 1 . @#,racket[(2)])] is just another
way of writing @racket[(+ 1 2)]. It is practically never a good idea
to write application expressions using this dot notation; it's just a
consequence of the way Scheme's syntax is defined.
consequence of the way Racket's syntax is defined.
Normally, @litchar{.} is allowed by the reader only with a
parenthesized sequence, and only before the last element of the
@ -245,6 +287,6 @@ conversion enables a kind of general infix notation:
]
This two-dot convention is non-traditional, and it has essentially
nothing to do with the dot notation for non-list pairs. PLT Scheme
nothing to do with the dot notation for non-list pairs. Racket
programmers use the infix convention sparingly---mostly for asymmetric
binary operators such as @scheme[<] and @scheme[is-a?].
binary operators such as @racket[<] and @racket[is-a?].

View File

@ -3,16 +3,16 @@
scribble/eval
"guide-utils.ss"
(for-label scheme/unit
scheme/class))
(for-label racket/unit
racket/class))
@(define toy-eval (make-base-eval))
@(interaction-eval #:eval toy-eval (require scheme/unit))
@(interaction-eval #:eval toy-eval (require racket/unit))
@(define-syntax-rule (schememod/eval [pre ...] form more ...)
@(define-syntax-rule (racketmod/eval [pre ...] form more ...)
(begin
(schememod pre ... form more ...)
(racketmod pre ... form more ...)
(interaction-eval #:eval toy-eval form)))
@title[#:tag "units" #:style 'toc]{Units@aux-elem{ (Components)}}
@ -40,15 +40,15 @@ re-exports some variables from the linked units for further linking.
The interface of a unit is described in terms of
@deftech{signatures}. Each signature is defined (normally within a
@scheme[module]) using @scheme[define-signature]. For example, the
@racket[module]) using @racket[define-signature]. For example, the
following signature, placed in a @filepath{toy-factory-sig.ss} file,
describes the exports of a component that implements a toy factory:
@margin-note{By convention, signature names with @litchar{^}.}
@schememod/eval[[#:file
@racketmod/eval[[#:file
"toy-factory-sig.ss"
scheme]
racket]
(define-signature toy-factory^
(build-toys (code:comment #, @tt{(integer? -> (listof toy?))})
@ -59,15 +59,15 @@ scheme]
(provide toy-factory^)
]
An implementation of the @scheme[toy-factory^] signature is written
using @scheme[define-unit] with an @scheme[export] clause that names
@scheme[toy-factory^]:
An implementation of the @racket[toy-factory^] signature is written
using @racket[define-unit] with an @racket[export] clause that names
@racket[toy-factory^]:
@margin-note{By convention, unit names with @litchar["@"].}
@schememod/eval[[#:file
@racketmod/eval[[#:file
"simple-factory-unit.ss"
scheme
racket
(require "toy-factory-sig.ss")]
@ -89,16 +89,16 @@ scheme
(provide simple-factory@)
]
The @scheme[toy-factory^] signature also could be referenced by a unit
The @racket[toy-factory^] signature also could be referenced by a unit
that needs a toy factory to implement something else. In that case,
@scheme[toy-factory^] would be named in an @scheme[import] clause.
@racket[toy-factory^] would be named in an @racket[import] clause.
For example, a toy store would get toys from a toy factory. (Suppose,
for the sake of an example with interesting features, that the store
is willing to sell only toys in a particular color.)
@schememod/eval[[#:file
@racketmod/eval[[#:file
"toy-store-sig.ss"
scheme]
racket]
(define-signature toy-store^
(store-color (code:comment #, @tt{(-> symbol?)})
@ -108,9 +108,9 @@ scheme]
(provide toy-store^)
]
@schememod/eval[[#:file
@racketmod/eval[[#:file
"toy-store-unit.ss"
scheme
racket
(require "toy-store-sig.ss"
"toy-factory-sig.ss")]
@ -142,15 +142,15 @@ scheme
Note that @filepath{toy-store-unit.ss} imports
@filepath{toy-factory-sig.ss}, but not
@filepath{simple-factory-unit.ss}. Consequently, the
@scheme[toy-store@] unit relies only on the specification of a toy
@racket[toy-store@] unit relies only on the specification of a toy
factory, not on a specific implementation.
@; ----------------------------------------
@section{Invoking Units}
The @scheme[simple-factory@] unit has no imports, so it can be
@tech{invoked} directly using @scheme[invoke-unit]:
The @racket[simple-factory@] unit has no imports, so it can be
@tech{invoked} directly using @racket[invoke-unit]:
@interaction[
#:eval toy-eval
@ -158,9 +158,9 @@ The @scheme[simple-factory@] unit has no imports, so it can be
(invoke-unit simple-factory@)
]
The @scheme[invoke-unit] form does not make the body definitions
The @racket[invoke-unit] form does not make the body definitions
available, however, so we cannot build any toys with this factory. The
@scheme[define-values/invoke-unit] form binds the identifiers of a
@racket[define-values/invoke-unit] form binds the identifiers of a
signature to the values supplied by a unit (to be @tech{invoked}) that
implements the signature:
@ -170,16 +170,16 @@ implements the signature:
(build-toys 3)
]
Since @scheme[simple-factory@] exports the @scheme[toy-factory^]
signature, each identifier in @scheme[toy-factory^] is defined by the
@scheme[define-values/invoke-unit/infer] form. The
@schemeidfont{/infer} part of the form name indicates that the
Since @racket[simple-factory@] exports the @racket[toy-factory^]
signature, each identifier in @racket[toy-factory^] is defined by the
@racket[define-values/invoke-unit/infer] form. The
@racketidfont{/infer} part of the form name indicates that the
identifiers bound by the declaration are inferred from
@scheme[simple-factory@].
@racket[simple-factory@].
Now that the identifiers in @scheme[toy-factory^] are defined, we can
also invoke @scheme[toy-store@], which imports @scheme[toy-factory^]
to produce @scheme[toy-store^]:
Now that the identifiers in @racket[toy-factory^] are defined, we can
also invoke @racket[toy-store@], which imports @racket[toy-factory^]
to produce @racket[toy-store^]:
@interaction[
#:eval toy-eval
@ -190,11 +190,11 @@ to produce @scheme[toy-store^]:
(get-inventory)
]
Again, the @schemeidfont{/infer} part
@scheme[define-values/invoke-unit/infer] determines that
@scheme[toy-store@] imports @scheme[toy-factory^], and so it supplies
the top-level bindings that match the names in @scheme[toy-factory^]
as imports to @scheme[toy-store@].
Again, the @racketidfont{/infer} part
@racket[define-values/invoke-unit/infer] determines that
@racket[toy-store@] imports @racket[toy-factory^], and so it supplies
the top-level bindings that match the names in @racket[toy-factory^]
as imports to @racket[toy-store@].
@; ----------------------------------------
@ -203,11 +203,11 @@ as imports to @scheme[toy-store@].
We can make our toy economy more efficient by having toy factories
that cooperate with stores, creating toys that do not have to be
repainted. Instead, the toys are always created using the store's
color, which the factory gets by importing @scheme[toy-store^]:
color, which the factory gets by importing @racket[toy-store^]:
@schememod/eval[[#:file
@racketmod/eval[[#:file
"store-specific-factory-unit.ss"
scheme
racket
(require "toy-factory-sig.ss")]
@ -229,14 +229,14 @@ scheme
(provide store-specific-factory@)
]
To invoke @scheme[store-specific-factory@], we need
@scheme[toy-store^] bindings to supply to the unit. But to get
@scheme[toy-store^] bindings by invoking @scheme[toy-store@], we will
To invoke @racket[store-specific-factory@], we need
@racket[toy-store^] bindings to supply to the unit. But to get
@racket[toy-store^] bindings by invoking @racket[toy-store@], we will
need a toy factory! The unit implementations are mutually dependent,
and we cannot invoke either before the other.
The solution is to @deftech{link} the units together, and then we can
invoke the combined units. The @scheme[define-compound-unit/infer] form
invoke the combined units. The @racket[define-compound-unit/infer] form
links any number of units to form a combined unit. It can propagate
imports and exports from the linked units, and it can satisfy each
unit's imports using the exports of other linked units.
@ -251,10 +251,10 @@ unit's imports using the exports of other linked units.
toy-store@))
]
The overall result above is a unit @scheme[toy-store+factory@] that
exports both @scheme[toy-factory^] and @scheme[toy-store^]. The
connection between @scheme[store-specific-factory@] and
@scheme[toy-store@] is inferred from the signatures that each imports
The overall result above is a unit @racket[toy-store+factory@] that
exports both @racket[toy-factory^] and @racket[toy-store^]. The
connection between @racket[store-specific-factory@] and
@racket[toy-store@] is inferred from the signatures that each imports
and exports.
This unit has no imports, so we can always invoke it:
@ -271,15 +271,15 @@ This unit has no imports, so we can always invoke it:
@section[#:tag "firstclassunits"]{First-Class Units}
The @scheme[define-unit] form combines @scheme[define] with a
@scheme[unit] form, similar to the way that @scheme[(define (f x)
....)] combines @scheme[define] followed by an identifier with an
implicit @scheme[lambda].
The @racket[define-unit] form combines @racket[define] with a
@racket[unit] form, similar to the way that @racket[(define (f x)
....)] combines @racket[define] followed by an identifier with an
implicit @racket[lambda].
Expanding the shorthand, the definition of @scheme[toy-store@] could
Expanding the shorthand, the definition of @racket[toy-store@] could
almost be written as
@schemeblock[
@racketblock[
(define toy-store@
(unit
(import toy-factory^)
@ -291,23 +291,23 @@ almost be written as
....))
]
A difference between this expansion and @scheme[define-unit] is that
the imports and exports of @scheme[toy-store@] cannot be
inferred. That is, besides combining @scheme[define] and
@scheme[unit], @scheme[define-unit] attaches static information to the
A difference between this expansion and @racket[define-unit] is that
the imports and exports of @racket[toy-store@] cannot be
inferred. That is, besides combining @racket[define] and
@racket[unit], @racket[define-unit] attaches static information to the
defined identifier so that its signature information is available
statically to @scheme[define-values/invoke-unit/infer] and other
statically to @racket[define-values/invoke-unit/infer] and other
forms.
Despite the drawback of losing static signature information,
@scheme[unit] can be useful in combination with other forms that work
with first-class values. For example, we could wrap a @scheme[unit]
that creates a toy store in a @scheme[lambda] to supply the store's
@racket[unit] can be useful in combination with other forms that work
with first-class values. For example, we could wrap a @racket[unit]
that creates a toy store in a @racket[lambda] to supply the store's
color:
@schememod/eval[[#:file
@racketmod/eval[[#:file
"toy-store-maker.ss"
scheme
racket
(require "toy-store-sig.ss"
"toy-factory-sig.ss")]
@ -340,9 +340,9 @@ scheme
(provide toy-store@-maker)
]
To invoke a unit created by @scheme[toy-store@-maker], we must use
@scheme[define-values/invoke-unit], instead of the
@schemeidfont{/infer} variant:
To invoke a unit created by @racket[toy-store@-maker], we must use
@racket[define-values/invoke-unit], instead of the
@racketidfont{/infer} variant:
@interaction[
#:eval toy-eval
@ -356,17 +356,17 @@ To invoke a unit created by @scheme[toy-store@-maker], we must use
(get-inventory)
]
In the @scheme[define-values/invoke-unit] form, the @scheme[(import
In the @racket[define-values/invoke-unit] form, the @racket[(import
toy-factory^)] line takes bindings from the current context that match
the names in @scheme[toy-factory^] (the ones that we created by
invoking @scheme[simple-factory@]), and it supplies them as imports to
@scheme[toy-store@]. The @scheme[(export toy-store^)] clause indicates
that the unit produced by @scheme[toy-store@-maker] will export
@scheme[toy-store^], and the names from that signature are defined
the names in @racket[toy-factory^] (the ones that we created by
invoking @racket[simple-factory@]), and it supplies them as imports to
@racket[toy-store@]. The @racket[(export toy-store^)] clause indicates
that the unit produced by @racket[toy-store@-maker] will export
@racket[toy-store^], and the names from that signature are defined
after invoking the unit.
To link a unit from @scheme[toy-store@-maker], we can use the
@scheme[compound-unit] form:
To link a unit from @racket[toy-store@-maker], we can use the
@racket[compound-unit] form:
@interaction[
#:eval toy-eval
@ -379,27 +379,27 @@ To link a unit from @scheme[toy-store@-maker], we can use the
[((TS : toy-store^)) toy-store@ TF])))
]
This @scheme[compound-unit] form packs a lot of information into one
place. The left-hand-side @scheme[TF] and @scheme[TS] in the
@scheme[link] clause are binding identifiers. The identifier
@scheme[TF] is essentially bound to the elements of
@scheme[toy-factory^] as implemented by
@scheme[store-specific-factory@]. The identifier @scheme[TS] is
similarly bound to the elements of @scheme[toy-store^] as implemented
by @scheme[toy-store@]. Meanwhile, the elements bound to @scheme[TS]
are supplied as imports for @scheme[store-specific-factory@], since
@scheme[TS] follows @scheme[store-specific-factory@]. The elements
bound to @scheme[TF] are similarly supplied to
@scheme[toy-store@]. Finally, @scheme[(export TF TS)] indicates that
the elements bound to @scheme[TF] and @scheme[TS] are exported from
This @racket[compound-unit] form packs a lot of information into one
place. The left-hand-side @racket[TF] and @racket[TS] in the
@racket[link] clause are binding identifiers. The identifier
@racket[TF] is essentially bound to the elements of
@racket[toy-factory^] as implemented by
@racket[store-specific-factory@]. The identifier @racket[TS] is
similarly bound to the elements of @racket[toy-store^] as implemented
by @racket[toy-store@]. Meanwhile, the elements bound to @racket[TS]
are supplied as imports for @racket[store-specific-factory@], since
@racket[TS] follows @racket[store-specific-factory@]. The elements
bound to @racket[TF] are similarly supplied to
@racket[toy-store@]. Finally, @racket[(export TF TS)] indicates that
the elements bound to @racket[TF] and @racket[TS] are exported from
the compound unit.
The above @scheme[compound-unit] form uses
@scheme[store-specific-factory@] as a first-class unit, even though
The above @racket[compound-unit] form uses
@racket[store-specific-factory@] as a first-class unit, even though
its information could be inferred. Every unit can be used as a
first-class unit, in addition to its use in inference contexts. Also,
various forms let a programmer bridge the gap between inferred and
first-class worlds. For example, @scheme[define-unit-binding] binds a
first-class worlds. For example, @racket[define-unit-binding] binds a
new identifier to the unit produced by an arbitrary expression; it
statically associates signature information to the identifier, and it
dynamically checks the signatures against the first-class unit
@ -407,18 +407,18 @@ produced by the expression.
@; ----------------------------------------
@section{Whole-@scheme[module] Signatures and Units}
@section{Whole-@racket[module] Signatures and Units}
In programs that use units, modules like @filepath{toy-factory-sig.ss}
and @filepath{simple-factory-unit.ss} are common. The
@scheme[scheme/signature] and @scheme[scheme/unit] module names can be
@racket[racket/signature] and @racket[racket/unit] module names can be
used as languages to avoid much of the boilerplate module, signature,
and unit declaration text.
For example, @filepath{toy-factory-sig.ss} can be written as
@schememod[
scheme/signature
@racketmod[
racket/signature
build-toys (code:comment #, @tt{(integer? -> (listof toy?))})
repaint (code:comment #, @tt{(toy? symbol? -> toy?)})
@ -426,14 +426,14 @@ toy? (code:comment #, @tt{(any/c -> boolean?)})
toy-color (code:comment #, @tt{(toy? -> symbol?)})
]
The signature @scheme[toy-factory^] is automatically provided from the
The signature @racket[toy-factory^] is automatically provided from the
module, inferred from the filename @filepath{toy-factory-sig.ss} by
replacing the @filepath{-sig.ss} suffix with @schemeidfont{^}.
replacing the @filepath{-sig.ss} suffix with @racketidfont{^}.
Similarly, @filepath{simple-factory-unit.ss} module can be written
@schememod[
scheme/unit
@racketmod[
racket/unit
(require "toy-factory-sig.ss")
@ -452,13 +452,13 @@ scheme/unit
(make-toy col))
]
The unit @scheme[simple-factory@] is automatically provided from the
The unit @racket[simple-factory@] is automatically provided from the
module, inferred from the filename @filepath{simple-factory-unit.ss} by
replacing the @filepath{-unit.ss} suffix with @schemeidfont["@"].
replacing the @filepath{-unit.ss} suffix with @racketidfont["@"].
@; ----------------------------------------
@(interaction-eval #:eval toy-eval (require scheme/contract))
@(interaction-eval #:eval toy-eval (require racket/contract))
@section{Contracts for Units}
@ -470,12 +470,12 @@ when a unit must conform to an already existing signature.
When contracts are added to a signature, then all units which implement
that signature are protected by those contracts. The following version
of the @scheme[toy-factory^] signature adds the contracts previously
of the @racket[toy-factory^] signature adds the contracts previously
written in comments:
@schememod/eval[[#:file
@racketmod/eval[[#:file
"contracted-toy-factory-sig.ss"
scheme]
racket]
(define-signature contracted-toy-factory^
((contracted
@ -486,12 +486,12 @@ scheme]
(provide contracted-toy-factory^)]
Now we take the previous implementation of @scheme[simple-factory@] and
implement this version of @scheme[toy-factory^] instead:
Now we take the previous implementation of @racket[simple-factory@] and
implement this version of @racket[toy-factory^] instead:
@schememod/eval[[#:file
@racketmod/eval[[#:file
"contracted-simple-factory-unit.ss"
scheme
racket
(require "contracted-toy-factory-sig.ss")]
@ -530,17 +530,17 @@ causes the appropriate contract errors.
However, sometimes we may have a unit that must conform to an
already existing signature that is not contracted. In this case,
we can create a unit contract with @scheme[unit/c] or use
the @scheme[define-unit/contract] form, which defines a unit which
we can create a unit contract with @racket[unit/c] or use
the @racket[define-unit/contract] form, which defines a unit which
has been wrapped with a unit contract.
For example, here's a version of @scheme[toy-factory@] which still
implements the regular @scheme[toy-factory^], but whose exports
For example, here's a version of @racket[toy-factory@] which still
implements the regular @racket[toy-factory^], but whose exports
have been protected with an appropriate unit contract.
@schememod/eval[[#:file
@racketmod/eval[[#:file
"wrapped-simple-factory-unit.ss"
scheme
racket
(require "toy-factory-sig.ss")]
@ -578,32 +578,32 @@ scheme
@; ----------------------------------------
@section{@scheme[unit] versus @scheme[module]}
@section{@racket[unit] versus @racket[module]}
As a form for modularity, @scheme[unit] complements @scheme[module]:
As a form for modularity, @racket[unit] complements @racket[module]:
@itemize[
@item{The @scheme[module] form is primarily for managing a universal
@item{The @racket[module] form is primarily for managing a universal
namespace. For example, it allows a code fragment to refer
specifically to the @scheme[car] operation from
@schememodname[scheme/base]---the one that extracts the first
specifically to the @racket[car] operation from
@racketmodname[racket/base]---the one that extracts the first
element of an instance of the built-in pair datatype---as
opposed to any number of other functions with the name
@scheme[car]. In other word, the @scheme[module] construct lets
@racket[car]. In other word, the @racket[module] construct lets
you refer to @emph{the} binding that you want.}
@item{The @scheme[unit] form is for parameterizing a code fragment
@item{The @racket[unit] form is for parameterizing a code fragment
with respect to most any kind of run-time value. For example,
it allows a code fragement for work with a @scheme[car]
it allows a code fragement for work with a @racket[car]
function that accepts a single argument, where the specific
function is determined later by linking the fragment to
another. In other words, the @scheme[unit] construct lets you
another. In other words, the @racket[unit] construct lets you
refer to @emph{a} binding that meets some specification.}
]
The @scheme[lambda] and @scheme[class] forms, among others, also allow
The @racket[lambda] and @racket[class] forms, among others, also allow
paremetrization of code with respect to values that are chosen
later. In principle, any of those could be implemented in terms of any
of the others. In practice, each form offers certain
@ -611,22 +611,22 @@ conveniences---such as allowing overriding of methods or especially
simple application to values---that make them suitable for different
purposes.
The @scheme[module] form is more fundamental than the others, in a
The @racket[module] form is more fundamental than the others, in a
sense. After all, a program fragment cannot reliably refer to
@scheme[lambda], @scheme[class], or @scheme[unit] form without the
namespace management provided by @scheme[module]. At the same time,
@racket[lambda], @racket[class], or @racket[unit] form without the
namespace management provided by @racket[module]. At the same time,
because namespace management is closely related to separate expansion
and compilation, @scheme[module] boundaries end up as
and compilation, @racket[module] boundaries end up as
separate-compilation boundaries in a way that prohibits mutual
dependencies among fragments. For similar reasons, @scheme[module]
dependencies among fragments. For similar reasons, @racket[module]
does not separate interface from implementation.
Use @scheme[unit] when @scheme[module] by itself almost works, but
Use @racket[unit] when @racket[module] by itself almost works, but
when separately compiled pieces must refer to each other, or when you
want a stronger separation between @defterm{interface} (i.e., the
parts that need to be known at expansion and compilation time) and
@defterm{implementation} (i.e., the run-time parts). More generally,
use @scheme[unit] when you need to parameterize code over functions,
use @racket[unit] when you need to parameterize code over functions,
datatypes, and classes, and when the parameterized code itself
provides definitions to be linked with other parameterized code.

View File

@ -19,8 +19,8 @@ represent symbols and lists.
@refdetails/gory["parse-vector"]{the syntax of vectors}
@examples[
(eval:alts @#,schemevalfont{#("a" "b" "c")} #("a" "b" "c"))
(eval:alts @#,schemevalfont{#(name (that tune))} #(name (that tune)))
(eval:alts @#,racketvalfont{#("a" "b" "c")} #("a" "b" "c"))
(eval:alts @#,racketvalfont{#(name (that tune))} #(name (that tune)))
(vector-ref #("a" "b" "c") 1)
(vector-ref #(name (that tune)) 1)
]
@ -29,10 +29,10 @@ Like strings, a vector is either mutable or immutable, and vectors
written directly as expressions are immutable.
Vector can be converted to lists and vice-versa via
@scheme[list->vector] and @scheme[vector->list]; such conversions are
@racket[list->vector] and @racket[vector->list]; such conversions are
particularly useful in combination with predefined procedures on
lists. When allocating extra lists seems too expensive, consider
using looping forms like @scheme[fold-for], which recognize vectors as
using looping forms like @racket[fold-for], which recognize vectors as
well as lists.
@examples[

View File

@ -6,14 +6,14 @@
@title[#:tag "void+undefined"]{Void and Undefined}
Some procedures or expression forms have no need for a result
value. For example, the @scheme[display] procedure is called only for
value. For example, the @racket[display] procedure is called only for
the side-effect of writing output. In such cases the result value is
normally a special constant that prints as @|void-const|. When the
result of an expression is simply @|void-const|, the REPL does not
print anything.
The @scheme[void] procedure takes any number of arguments and returns
@|void-const|. (That is, the identifier @schemeidfont{void} is bound
The @racket[void] procedure takes any number of arguments and returns
@|void-const|. (That is, the identifier @racketidfont{void} is bound
to a procedure that returns @|void-const|, instead of being bound
directly to @|void-const|.)
@ -26,9 +26,9 @@ directly to @|void-const|.)
A constant that prints as @undefined-const is used as the result of a
reference to a local binding when the binding is not yet
initialized. Such early references are not possible for bindings that
correspond to procedure arguments, @scheme[let] bindings, or
@scheme[let*] bindings; early reference requires a recursive binding
context, such as @scheme[letrec] or local @scheme[define]s in a
correspond to procedure arguments, @racket[let] bindings, or
@racket[let*] bindings; early reference requires a recursive binding
context, such as @racket[letrec] or local @racket[define]s in a
procedure body. Also, early references to top-level and module-level
bindings raise an exception, instead of producing
@|undefined-const|. For these reasons, @undefined-const rarely

View File

@ -3,79 +3,80 @@
scribble/eval
scribble/bnf
"guide-utils.ss"
(for-label scheme/enter))
(for-label racket/enter))
@(define piece-eval (make-base-eval))
@title[#:tag "intro"]{Welcome to PLT Scheme}
@title[#:tag "intro"]{Welcome to Racket}
Depending on how you look at it, @bold{PLT Scheme} is
Depending on how you look at it, @bold{Racket} is
@itemize[
@item{a @defterm{programming language}---a descendant of Scheme, which
is a dialect of Lisp;
@item{a @defterm{programming language}---a dialect of Lisp and a
descendant of Scheme;
@margin-note{See @secref["dialects"] for more information on
other dialects of Scheme and how they relate to PLT Scheme.}}
other dialects of Lisp and how they relate to Racket.}}
@item{a @defterm{family} of programming languages---variants of
Scheme, and more; or}
Racket, and more; or}
@item{a set of @defterm{tools}---for using a family of programming languages.}
]
Where there is no room for confusion, we use simply @defterm{Scheme}
to refer to any of these facets of PLT Scheme.
Where there is no room for confusion, we use simply @defterm{Racket}.
PLT Scheme's two main tools are
Racket's main tools are
@itemize[
@tool["MzScheme"]{the core compiler, interpreter, and run-time
system; and}
@tool[@exec{racket}]{the core compiler, interpreter, and run-time system;}
@tool["DrScheme"]{the programming environment (which runs on top of
MzScheme).}
@tool["DrRacket"]{the programming environment; and}
@tool[@exec{raco}]{a command-line tool for executing @bold{Ra}cket
@bold{co}mmands that install packages, build libraries, and more.}
]
Most likely, you'll want to explore PLT Scheme using DrScheme,
Most likely, you'll want to explore the Racket language using DrRacket,
especially at the beginning. If you prefer, you can also work with the
command-line @exec{mzscheme} interpreter and your favorite text
command-line @exec{racket} interpreter and your favorite text
editor. The rest of this guide presents the language mostly
independent of your choice of editor.
If you're using DrScheme, you'll need to choose the proper language,
because DrScheme accommodates many different variants of
Scheme. Assuming that you've never used DrScheme before, start it up,
type the line
If you're using DrRacket, you'll need to choose the proper language,
because DrRacket accommodates many different variants of Racket, as
well as other languages. Assuming that you've never used DrRacket
before, start it up, type the line
@schememod[scheme]
@racketmod[racket]
in DrScheme's top text area, and then click the @onscreen{Run} button
that's above the text area. DrScheme then understands that you mean to
work in the normal variant of Scheme (as opposed to the smaller
@schememodname[scheme/base], or many other possibilities).
in DrRacket's top text area, and then click the @onscreen{Run} button
that's above the text area. DrRacket then understands that you mean to
work in the normal variant of Racket (as opposed to the smaller
@racketmodname[racket/base] or many other possibilities).
@margin-note{@secref["more-hash-lang"] describes some of the other
possibilities.}
If you've used DrScheme before with something other than a program
that starts @hash-lang[], DrScheme will remember the last language
If you've used DrRacket before with something other than a program
that starts @hash-lang[], DrRacket will remember the last language
that you used, instead of inferring the language from the @hash-lang[]
line. In that case, use the @menuitem["Language" "Choose Language..."]
menu item. In the dialog that appears, select the first item,
which is @onscreen{Module}. Put the @hash-lang[] line above in the top
menu item. In the dialog that appears, select the first item, which
tells DrRacket to use the language that is declared in a source
program via @hash-lang[]. Put the @hash-lang[] line above in the top
text area, still.
@; ----------------------------------------------------------------------
@section{Interacting with Scheme}
@section{Interacting with Racket}
DrScheme's bottom text area and the @exec{mzscheme} command-line
program (when started with no options) both act as a kind of
calculator. You type a Scheme expression, hit return, and the answer
is printed. In the terminology of Scheme, this kind of calculator is
DrRacket's bottom text area and the @exec{racket} command-line program
(when started with no options) both act as a kind of calculator. You
type a Racket expression, hit the Return key, and the answer is
printed. In the terminology of Racket, this kind of calculator is
called a @idefterm{read-eval-print loop} or @deftech{REPL}.
A number by itself is an expression, and the answer is just the
@ -88,20 +89,20 @@ 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
Racket uses parentheses to wrap larger expressions---almost any kind
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 function @scheme[substring] with the arguments
@scheme["the boy out of the country"], @scheme[4], and @scheme[7]:
the built-in function @racket[substring] with the arguments
@racket["the boy out of the country"], @racket[4], and @racket[7]:
@interaction[(substring "the boy out of the country" 4 7)]
@; ----------------------------------------------------------------------
@section{Definitions and Interactions}
You can define your own functions that work like @scheme[substring] by
using the @scheme[define] form, like this:
You can define your own functions that work like @racket[substring] by
using the @racket[define] form, like this:
@def+int[
#:eval piece-eval
@ -111,48 +112,48 @@ using the @scheme[define] form, like this:
(extract "the country out of the boy")
]
Although you can evaluate the @scheme[define] form in the @tech{REPL},
Although you can evaluate the @racket[define] form in the @tech{REPL},
definitions are normally a part of a program that you want to keep and
use later. So, in DrScheme, you'd normally put the definition in the
use later. So, in DrRacket, you'd normally put the definition in the
top text area---called the @deftech{definitions area}---along with the
@hash-lang[] prefix:
@schememod[
scheme
@racketmod[
racket
code:blank
(define (extract str)
(substring str 4 7))
]
If calling @scheme[(extract "the boy")] is part of the main action of
If calling @racket[(extract "the boy")] is part of the main action of
your program, that would go in the @tech{definitions area}, too. But
if it was just an example expression that you were using to explore
@scheme[extract], then you'd more likely leave the @tech{definitions
@racket[extract], then you'd more likely leave the @tech{definitions
area} as above, click @onscreen{Run}, and then evaluate
@scheme[(extract "the boy")] in the @tech{REPL}.
@racket[(extract "the boy")] in the @tech{REPL}.
With @exec{mzscheme}, you'd save the above text in a file using your
favorite editor. If you save it as @filepath{extract.ss}, then after starting
@exec{mzscheme} in the same directory, you'd evaluate the following
With @exec{racket}, you'd save the above text in a file using your
favorite editor. If you save it as @filepath{extract.rkt}, then after starting
@exec{racket} in the same directory, you'd evaluate the following
sequence:
@interaction[
#:eval piece-eval
(eval:alts (enter! "extract.ss") (void))
(eval:alts (enter! "extract.rkt") (void))
(extract "the gal out of the city")
]
The @scheme[enter!] form both loads the code and switches the
evaluation context to the inside of the module, just like DrScheme's
The @racket[enter!] form both loads the code and switches the
evaluation context to the inside of the module, just like DrRacket's
@onscreen{Run} button.
@; ----------------------------------------------------------------------
@section{Creating Executables}
If your file (or @tech{definitions area} in DrScheme) contains
If your file (or @tech{definitions area} in DrRacket) contains
@schememod[
scheme
@racketmod[
racket
(define (extract str)
(substring str 4 7))
@ -166,14 +167,13 @@ options:
@itemize[
@item{In DrScheme, you can select the @menuitem["Scheme" "Create
@item{In DrRacket, you can select the @menuitem["Racket" "Create
Executable..."] menu item.}
@item{From a command-line prompt, run @exec{mzc --exe
@nonterm{dest-filename} @nonterm{src-filename}}, where
@nonterm{src-filename} contains the program. See @secref[#:doc
'(lib "scribblings/mzc/mzc.scrbl") "exe"] for more
information.}
@item{From a command-line prompt, run @exec{raco exe
@nonterm{src-filename}}, where @nonterm{src-filename} contains
the program. See @secref[#:doc '(lib
"scribblings/mzc/mzc.scrbl") "exe"] for more information.}
@item{With Unix or Mac OS X, you can turn the program file into an
executable script by inserting the line
@ -181,32 +181,32 @@ options:
@margin-note{See @secref["scripts"] for more information on
script files.}
@verbatim[#:indent 2]{#! /usr/bin/env mzscheme}
@verbatim[#:indent 2]{#! /usr/bin/env racket}
at the very beginning of the file. Also, change the file
permissions to executable using @exec{chmod +x
@nonterm{filename}} on the command line.
The script works as long as @exec{mzscheme} is in the user's
The script works as long as @exec{racket} is in the user's
executable search path. Alternately, use a full path to
@exec{mzscheme} after @tt{#!} (with a space between @tt{#!}
@exec{racket} after @tt{#!} (with a space between @tt{#!}
and the path), in which case the user's executable search path
does not matter.}
]
@; ----------------------------------------------------------------------
@section[#:tag "use-module"]{A Note to Readers with Scheme/Lisp Experience}
@section[#:tag "use-module"]{A Note to Readers with Lisp/Scheme Experience}
If you already know something about Scheme or Lisp, you might be
If you already know something about Racket or Lisp, you might be
tempted to put just
@schemeblock[
@racketblock[
(define (extract str)
(substring str 4 7))
]
into @filepath{extract.scm} and run @exec{mzscheme} with
into @filepath{extract.scm} and run @exec{racket} with
@interaction[
#:eval piece-eval
@ -214,18 +214,18 @@ into @filepath{extract.scm} and run @exec{mzscheme} with
(extract "the dog out")
]
That will work, because @exec{mzscheme} is willing to imitate a
That will work, because @exec{racket} is willing to imitate a
traditional Scheme environment, but we strongly recommend against using
@scheme[load] or writing programs outside of a module.
@racket[load] or writing programs outside of a module.
Writing definitions outside of a module leads to bad error messages,
bad performance, and awkward scripting to combine and run
programs. The problems are not specific to @exec{mzscheme}; they're
programs. The problems are not specific to @exec{racket}; they're
fundamental limitations of the traditional top-level environment,
which Scheme and Lisp implementations have historically fought with ad
hoc command-line flags, compiler directives, and build tools. The
module system is to designed to avoid the problems, so start with
@hash-lang[], and you'll be happier with PLT Scheme in the long run.
@hash-lang[], and you'll be happier with Racket in the long run.
@; ----------------------------------------------------------------------

View File

@ -8,7 +8,7 @@
@title[#:tag "define-struct"]{Defining Structure Types: @racket[struct]}
@guideintro["define-struct"]{@racket[define-struct]}
@guideintro["define-struct"]{@racket[struct]}
@defform/subs[(struct id maybe-super (field ...)
struct-option ...)

View File

@ -2304,6 +2304,8 @@ expression).
@;------------------------------------------------------------------------
@section[#:tag "quasiquote"]{Quasiquoting: @racket[quasiquote], @racket[unquote], and @racket[unquote-splicing]}
@guideintro["qq"]{@racket[quasiquote]}
@defform[(quasiquote datum)]{
The same as @racket[(quote datum)] if @racket[datum] does not include