racket/collects/scribblings/htdp-langs/advanced.scrbl
2012-06-25 19:15:09 -04:00

320 lines
11 KiB
Racket

#lang scribble/doc
@(require "common.rkt" "std-grammar.rkt" "prim-ops.rkt"
(for-label lang/htdp-advanced))
@title[#:tag "advanced"]{Advanced Student}
@declare-exporting[lang/htdp-advanced]
@racketgrammar*+qq[
#:literals (define define-struct define-datatype lambda λ cond else if and or require lib planet
local let let* letrec time begin begin0 set! delay shared recur when case match unless
; match
_ cons list list* struct vector box
check-expect check-within check-member-of check-range check-error)
(check-expect check-within check-error check-member-of check-range require)
[program (code:line def-or-expr ...)]
[def-or-expr definition
expr
test-case
library-require]
[definition (define (name variable ...) expr)
(define name expr)
(define-struct name (name ...))
(define-datatype name (name name ...) ...)]
[expr (begin expr expr ...)
(begin0 expr expr ...)
(set! variable expr)
(delay expr)
(lambda (variable ...) expr)
(λ (variable ...) expr)
(local [definition ...] expr)
(letrec ([name expr] ...) expr)
(shared ([name expr] ...) expr)
(let ([name expr] ...) expr)
(let name ([name expr] ...) expr)
(let* ([name expr] ...) expr)
(recur name ([name expr] ...) expr)
(code:line (expr expr ...))
(cond [expr expr] ... [expr expr])
(cond [expr expr] ... [else expr])
(case expr [(choice choice ...) expr] ...
[(choice choice ...) expr])
(case expr [(choice choice ...) expr] ...
[else expr])
(match expr [pattern expr] ...)
(if expr expr expr)
(when expr expr)
(unless expr expr)
(and expr expr expr ...)
(or expr expr expr ...)
(time expr)
(code:line name)
(code:line @#,elem{@racketvalfont{'}@racket[_quoted]})
(code:line @#,elem{@racketvalfont{`}@racket[_quasiquoted]})
number
boolean
string
character]
[choice (code:line name)
number]
[pattern _
name
number
true
false
string
character
@#,elem{@racketvalfont{'}@racket[_quoted]}
@#,elem{@racketvalfont{`}@racket[_quasiquoted-pattern]}
(cons pattern pattern)
(list pattern ...)
(list* pattern ...)
(struct id (pattern ...))
(vector pattern ...)
(box pattern)]
[quasiquoted-pattern name
number
string
character
(quasiquoted-pattern ...)
@#,elem{@racketvalfont{'}@racket[_quasiquoted-pattern]}
@#,elem{@racketvalfont{`}@racket[_quasiquoted-pattern]}
@#,elem{@racketfont[","]@racket[_pattern]}
@#,elem{@racketfont[",@"]@racket[_pattern]}]
]
@prim-nonterms[("advanced") define define-struct]
@prim-variables[("advanced") empty true false .. ... .... ..... ......]
@; ----------------------------------------------------------------------
@section[#:tag "advanced-syntax"]{Syntax for Advanced}
In Advanced, @racket[set!] can be used to mutate variables, and
@racket[define-struct]'s structures are mutatable. @racket[define] and
@racket[lambda] can define functions of zero arguments, and function calls can
invoke functions of zero arguments.
@defform[(lambda (variable ...) expression)]{
Creates a function that takes as many arguments as given @racket[variable]s,
and whose body is @racket[expression].}
@defform[(λ (variable ...) expression)]{
The Greek letter @racket[λ] is a synonym for @racket[lambda].}
@defform/none[(expression expression ...)]{
Calls the function that results from evaluating the first
@racket[expression]. The value of the call is the value of function's body when
every instance of @racket[name]'s variables are replaced by the values of the
corresponding @racket[expression]s.
The function being called must come from either a definition appearing before the
function call, or from a @racket[lambda] expression. The number of argument
@racket[expression]s must be the same as the number of arguments expected by
the function.}
@; ----------------------------------------------------------------------
@defform[(define-datatype dataype-name [variant-name field-name ...] ...)]{
A short-hand for defining a group of related structures. The following @racket[define-datatype]:
@racketblock[
(define-datatype datatype-name
[variant-name field-name (unsyntax @racketidfont{...})]
(unsyntax @racketidfont{...}))
]
is equivalent to:
@racketblock[
(define ((unsyntax @racket[datatype-name])? x)
(or ((unsyntax @racket[variant-name])? x) (unsyntax @racketidfont{...})))
(define-struct variant-name (field-name (unsyntax @racketidfont{...})))
(unsyntax @racketidfont{...})
]}
@defform[(begin expression expression ...)]{
Evaluates the @racket[expression]s in order from left to right. The value of
the @racket[begin] expression is the value of the last @racket[expression].}
@defform[(begin0 expression expression ...)]{
Evaluates the @racket[expression]s in order from left to right. The value of
the @racket[begin] expression is the value of the first @racket[expression].}
@defform[(set! variable expression)]{
Evaluates @racket[expression], and then mutates the @racket[variable]
to have @racket[expression]'s value. The @racket[variable] must be defined
by @racket[define], @racket[letrec], @racket[let*], or @racket[let].}
@defform[(delay expression)]{
Produces a ``promise'' to evaluate @racket[expression]. The @racket[expression]
is not evaluated until the promise is forced with @racket[force]; when
the promise is forced, the result is recorded, so that any further
@racket[force] of the promise immediately produces the remembered value.}
@defform[(shared ([name expression] ...) expression)]{
Like @racket[letrec], but when an @racket[expression] next to an @racket[id]
is a @racket[cons], @racket[list], @racket[vector], quasiquoted
expression, or @racketidfont{make-}@racket[_struct-name] from a
@racket[define-struct], the @racket[expression] can refer directly to any
@racket[name], not just @racket[name]s defined earlier. Thus,
@racket[shared] can be used to create cyclic data structures.}
@; ----------------------------------------------------------------------
@defform[(recur name ([name expression] ...) expression)]{
A short-hand syntax for recursive loops. The first @racket[name] corresponds to
the name of the recursive function. The @racket[name]s in the parenthesis are
the function's arguments, and each corresponding @racket[expression] is a
value supplied for that argument in an initial starting call of the
function. The last @racket[expression] is the body of the function.
More precisely, the following @racket[recur]:
@racketblock[
(recur func-name ([arg-name arg-expression] (unsyntax @racketidfont{...}))
body-expression)
]
is equivalent to:
@racketblock[
(local [(define (func-name arg-name (unsyntax @racketidfont{...})) body-expression)]
(func-name arg-expression (unsyntax @racketidfont{...})))
]}
@defform/none[(let name ([name expression] ...) expression)]{
An alternate syntax for @racket[recur].}
@; ----------------------------------------------------------------------
@defform[(case expression [(choice ...) expression] ... [(choice ...) expression])]{
A @racket[case] form contains one or more clauses. Each clause contains a
choices (in parentheses)---either numbers or names---and an answer
@racket[expression]. The initial @racket[expression] is evaluated, and its
value is compared to the choices in each clause, where the lines are considered
in order. The first line that contains a matching choice provides an answer
@racket[expression] whose value is the result of the whole @racket[case]
expression. Numbers match with the numbers in the choices, and symbols match
with the names. If none of the lines contains a matching choice, it is an
error.}
@defform/none[#:literals (case else)
(case expression [(choice ...) expression] ... [else expression])]{
This form of @racket[case] is similar to the prior one, except that the final
@racket[else] clause is taken if no clause contains a choice matching the value
of the initial @racket[expression].}
@; ----------------------------------------------------------------------
@defform[(match expression [pattern expression] ...)]{
A @racket[match] form contains one or more clauses that are surrounded by
square brackets. Each clause contains a pattern---a description of a value---and
an answer @racket[expression]. The initial @racket[expression] is evaluated,
and its value is matched against the pattern in each clause, where the clauses are
considered in order. The first clause that contains a matching pattern provides
an answer @racket[expression] whose value is the result of the whole
@racket[match] expression. This @racket[expression] may reference identifiers
defined in the matching pattern. If none of the clauses contains a matching
pattern, it is an error.}
@; ----------------------------------------------------------------------
@defform[(when test-expression body-expression)]{
If @racket[test-expression] evaluates to @racket[true], the result of the
@racket[when] expression is the result of evaluating the
@racket[body-expression], otherwise the result is @racket[(void)] and the
@racket[body-expression] is not evaluated. If the result of evaluating the
@racket[test-expression] is neither @racket[true] nor @racket[false], it is an
error.}
@defform[(unless test-expression body-expression)]{
Like @racket[when], but the @racket[body-expression] is evaluated when the
@racket[test-expression] produces @racket[false] instead of @racket[true].}
@section[#:tag "advanced-common-syntax"]{Common Syntaxes}
The following syntaxes behave the same in the @emph{Advanced}
level as they did in the @secref["intermediate-lam"] level.
@(intermediate-forms lambda
local
letrec
let*
let
time
define
define-struct)
@(define-forms/normal define)
@(prim-forms ("advanced")
define
lambda
define-struct
@{In Advanced, @racket[define-struct] introduces one additional function:
@itemize[
@item{@racketidfont{set-}@racket[_structure-name]@racketidfont{-}@racket[_field-name]@racketidfont{!}
: takes an instance of the structure and a value, and
mutates the instance's field to the given value.}]}
define-wish
cond
else
if
and
or
check-expect
check-within
check-error
check-member-of
check-range
require
true false
#:with-beginner-function-call #f)
@; ----------------------------------------
@section[#:tag "advanced-pre-defined"]{Pre-Defined Functions}
@(require (submod lang/htdp-advanced procedures))
@(render-sections (docs) #'here "htdp-advanced")
@;prim-op-defns['(lib "htdp-advanced.rkt" "lang") #'here '()]