You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
typesetting/quad/qtest/mds/forms.md

2245 lines
78 KiB
Markdown

5 years ago
# Expressions and Definitions
The \[missing\] chapter introduced some of Rackets syntactic forms:
definitions, procedure applications, conditionals, and so on. This
section provides more details on those forms, plus a few additional
basic forms.
1 Notation
2 Identifiers and Binding
3 Function Calls \(Procedure Applications\)
3.1 Evaluation Order and Arity
3.2 Keyword Arguments
3.3 The `apply` Function
4 Functions \(Procedures\): `lambda`
4.1 Declaring a Rest Argument
4.2 Declaring Optional Arguments
4.3 Declaring Keyword Arguments
4.4 Arity-Sensitive Functions: `case-lambda`
5 Definitions: `define`
5.1 Function Shorthand
5.2 Curried Function Shorthand
5.3 Multiple Values and `define-values`
5.4 Internal Definitions
6 Local Binding
6.1 Parallel Binding: `let`
6.2 Sequential Binding: `let*`
6.3 Recursive Binding: `letrec`
6.4 Named `let`
6.5 Multiple Values: `let-values`, `let*-values`, `letrec-values`
7 Conditionals
7.1 Simple Branching: `if`
7.2 Combining Tests: `and` and `or`
7.3 Chaining Tests: `cond`
8 Sequencing
8.1 Effects Before: `begin`
8.2 Effects After: `begin0`
8.3 Effects If...: `when` and `unless`
9 Assignment: `set!`
9.1 Guidelines for Using Assignment
9.2 Multiple Values: `set!-values`
10 Quoting: `quote` and `'`
11 Quasiquoting: `quasiquote` and ``
12 Simple Dispatch: `case`
13 Dynamic Binding: `parameterize`
## 1. Notation
This chapter \(and the rest of the documentation\) uses a slightly
different notation than the character-based grammars of the \[missing\]
chapter. The grammar for a use of a syntactic form `something` is shown
like this:
```racket
(something [id ...+] an-expr ...)
```
The italicized meta-variables in this specification, such as `id` and
`an-expr`, use the syntax of Racket identifiers, so `an-expr` is one
meta-variable. A naming convention implicitly defines the meaning of
many meta-variables:
* A meta-variable that ends in `id` stands for an identifier, such as
`x` or `my-favorite-martian`.
* A meta-identifier that ends in `keyword` stands for a keyword, such as
`#:tag`.
* A meta-identifier that ends with `expr` stands for any sub-form, and
it will be parsed as an expression.
* A meta-identifier that ends with `body` stands for any sub-form; it
will be parsed as either a local definition or an expression. A `body`
can parse as a definition only if it is not preceded by any
expression, and the last `body` must be an expression; see also
Internal Definitions.
Square brackets in the grammar indicate a parenthesized sequence of
forms, where square brackets are normally used \(by convention\). That
is, square brackets _do not_ mean optional parts of the syntactic form.
A `...` indicates zero or more repetitions of the preceding form, and
`...+` 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
`something`:
```racket
(something [x])
(something [x] (+ 1 2))
(something [x my-favorite-martian x] (+ 1 2) #f)
```
Some syntactic-form specifications refer to meta-variables that are not
implicitly defined and not previously defined. Such meta-variables are
defined after the main form, using a BNF-like format for alternatives:
```racket
(something-else [thing ...+] an-expr ...)
thing = thing-id
| thing-keyword
```
The above example says that, within a `something-else` form, a `thing`
is either an identifier or a keyword.
## 2. Identifiers and Binding
The context of an expression determines the meaning of identifiers that
appear in the expression. In particular, starting a module with the
language `racket`, as in
`#lang` `racket`
means that, within the module, the identifiers described in this guide
start with the meaning described here: `cons` refers to the function
that creates a pair, `car` refers to the function that extracts the
first element of a pair, and so on.
> +\[missing\] introduces the syntax of identifiers.
Forms like `define`, `lambda`, and `let` associate a meaning with one or
more identifiers; that is, they _bind_ identifiers. The part of the
program for which the binding applies is the _scope_ of the binding. The
set of bindings in effect for a given expression is the expressions
_environment_.
For example, in
```racket
#lang racket
(define f
(lambda (x)
(let ([y 5])
(+ x y))))
(f 10)
```
the `define` is a binding of `f`, the `lambda` has a binding for `x`,
and the `let` has a binding for `y`. The scope of the binding for `f` is
the entire module; the scope of the `x` binding is `(let ([y 5]) (+ x
y))`; and the scope of the `y` binding is just `(+ x y)`. The
environment of `(+ x y)` includes bindings for `y`, `x`, and `f`, as
well as everything in `racket`.
A module-level `define` can bind only identifiers that are not already
defined or `require`d into the module. A local `define` or other binding
forms, however, can give a new local binding for an identifier that
already has a binding; such a binding _shadows_ the existing binding.
Examples:
```racket
(define f
(lambda (append)
(define cons (append "ugly" "confusing"))
(let ([append 'this-was])
(list append cons))))
> (f list)
'(this-was ("ugly" "confusing"))
```
Similarly, a module-level `define` can shadow a binding from the
modules language. For example, `(define cons 1)` in a `racket` module
shadows the `cons` that is provided by `racket`. Intentionally shadowing
a language binding is rarely a good idea—especially for widely used
bindings like `cons`—but shadowing relieves a programmer from having to
avoid every obscure binding that is provided by a language.
Even identifiers like `define` and `lambda` get their meanings from
bindings, though they have _transformer_ bindings \(which means that
they indicate syntactic forms\) instead of value bindings. Since
`define` has a transformer binding, the identifier `define` cannot be
used by itself to get a value. However, the normal binding for `define`
can be shadowed.
Examples:
```racket
> define
eval:1:0: define: bad syntax
in: define
> (let ([define 5]) define)
5
```
Again, shadowing standard bindings in this way is rarely a good idea,
but the possibility is an inherent part of Rackets flexibility.
## 3. Function Calls \(Procedure Applications\)
An expression of the form
```racket
(proc-expr arg-expr ...)
```
is a function call—also known as a _procedure application_—when
`proc-expr` is not an identifier that is bound as a syntax transformer
\(such as `if` or `define`\).
### 3.1. Evaluation Order and Arity
A function call is evaluated by first evaluating the `proc-expr` and all
`arg-expr`s in order \(left to right\). Then, if `proc-expr` produces a
function that accepts as many arguments as supplied `arg-expr`s, the
function is called. Otherwise, an exception is raised.
Examples:
```racket
> (cons 1 null)
'(1)
> (+ 1 2 3)
6
> (cons 1 2 3)
cons: arity mismatch;
the expected number of arguments does not match the given
number
expected: 2
given: 3
arguments...:
1
2
3
> (1 2 3)
application: not a procedure;
expected a procedure that can be applied to arguments
given: 1
arguments...:
2
3
```
Some functions, such as `cons`, accept a fixed number of arguments. Some
functions, such as `+` or `list`, accept any number of arguments. Some
functions accept a range of argument counts; for example `substring`
accepts either two or three arguments. A functions _arity_ is the
number of arguments that it accepts.
### 3.2. Keyword Arguments
Some functions accept _keyword arguments_ in addition to by-position
arguments. For that case, an `arg` can be an `arg-keyword arg-expr`
sequence instead of just a `arg-expr`:
> +\[missing\] introduces keywords.
```racket
(proc-expr arg ...)
arg = arg-expr
| arg-keyword arg-expr
```
For example,
`(go` `"super.rkt"` `#:mode` `'fast)`
calls the function bound to `go` with `"super.rkt"` as a by-position
argument, and with `'fast` as an argument associated with the `#:mode`
keyword. A keyword is implicitly paired with the expression that follows
it.
Since a keyword by itself is not an expression, then
`(go` `"super.rkt"` `#:mode` `#:fast)`
is a syntax error. The `#:mode` keyword must be followed by an
expression to produce an argument value, and `#:fast` is not an
expression.
The order of keyword `arg`s determines the order in which `arg-expr`s
are evaluated, but a function accepts keyword arguments independent of
their position in the argument list. The above call to `go` can be
equivalently written
`(go` `#:mode` `'fast` `"super.rkt")`
> +\[missing\] in \[missing\] provides more on procedure applications.
### 3.3. The `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 `+` to all of the items in a list:
```racket
(define (avg lst) ; doesnt work...
(/ (+ lst) (length lst)))
```
```racket
> (avg '(1 2 3))
+: contract violation
expected: number?
given: '(1 2 3)
```
```racket
(define (avg lst) ; doesnt always work...
(/ (+ (list-ref lst 0) (list-ref lst 1) (list-ref lst 2))
(length lst)))
```
```racket
> (avg '(1 2 3))
2
> (avg '(1 2))
list-ref: index too large for list
index: 2
in: '(1 2)
```
The `apply` function offers a way around this restriction. It takes a
function and a _list_ argument, and it applies the function to the
values in the list:
```racket
(define (avg lst)
(/ (apply + lst) (length lst)))
```
```racket
> (avg '(1 2 3))
2
> (avg '(1 2))
3/2
> (avg '(1 2 3 4))
5/2
```
As a convenience, the `apply` function accepts additional arguments
between the function and the list. The additional arguments are
effectively `cons`ed onto the argument list:
```racket
(define (anti-sum lst)
(apply - 0 lst))
```
```racket
> (anti-sum '(1 2 3))
-6
```
The `apply` function accepts keyword arguments, too, and it passes them
along to the called function:
```racket
(apply go #:mode 'fast '("super.rkt"))
(apply go '("super.rkt") #:mode 'fast)
```
Keywords that are included in `apply`s list argument do not count as
keyword arguments for the called function; instead, all arguments in
this list are treated as by-position arguments. To pass a list of
keyword arguments to a function, use the `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
`keyword<?`\), and the second list contains a corresponding argument for
each keyword. The third list contains by-position function arguments, as
for `apply`.
```racket
(keyword-apply go
'(#:mode)
'(fast)
'("super.rkt"))
```
## 4. Functions \(Procedures\): `lambda`
A `lambda` expression creates a function. In the simplest case, a
`lambda` expression has the form
```racket
(lambda (arg-id ...)
body ...+)
```
A `lambda` form with _n_ `arg-id`s accepts _n_ arguments:
```racket
> ((lambda (x) x)
1)
1
> ((lambda (x y) (+ x y))
1 2)
3
> ((lambda (x y) (+ x y))
1)
#<procedure>: arity mismatch;
the expected number of arguments does not match the given
number
expected: 2
given: 1
arguments...:
1
```
### 4.1. Declaring a Rest Argument
A `lambda` expression can also have the form
```racket
(lambda rest-id
body ...+)
```
That is, a `lambda` expression can have a single `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 `rest-id`.
Examples:
```racket
> ((lambda x x)
1 2 3)
'(1 2 3)
> ((lambda x x))
'()
> ((lambda x (car x))
1 2 3)
1
```
Functions with a `rest-id` often use `apply` to call another function
that accepts any number of arguments.
> +The `apply` Function describes `apply`.
Examples:
```racket
(define max-mag
(lambda nums
(apply max (map magnitude nums))))
> (max 1 -2 0)
1
> (max-mag 1 -2 0)
2
```
The `lambda` form also supports required arguments combined with a
`rest-id`:
```racket
(lambda (arg-id ...+ . rest-id)
body ...+)
```
The result of this form is a function that requires at least as many
arguments as `arg-id`s, and also accepts any number of additional
arguments.
Examples:
```racket
(define max-mag
(lambda (num . nums)
(apply max (map magnitude (cons num nums)))))
> (max-mag 1 -2 0)
2
> (max-mag)
max-mag: arity mismatch;
the expected number of arguments does not match the given
number
expected: at least 1
given: 0
```
A `rest-id` variable is sometimes called a _rest argument_, because it
accepts the “rest” of the function arguments.
### 4.2. Declaring Optional Arguments
Instead of just an identifier, an argument \(other than a rest
argument\) in a `lambda` form can be specified with an identifier and a
default value:
```racket
(lambda gen-formals
body ...+)
gen-formals = (arg ...)
| rest-id
| (arg ...+ . rest-id)
arg = arg-id
| [arg-id default-expr]
```
An argument of the form `[arg-id default-expr]` is optional. When the
argument is not supplied in an application, `default-expr` produces the
default value. The `default-expr` can refer to any preceding `arg-id`,
and every following `arg-id` must have a default as well.
Examples:
```racket
(define greet
(lambda (given [surname "Smith"])
(string-append "Hello, " given " " surname)))
> (greet "John")
"Hello, John Smith"
> (greet "John" "Doe")
"Hello, John Doe"
```
```racket
(define greet
(lambda (given [surname (if (equal? given "John")
"Doe"
"Smith")])
(string-append "Hello, " given " " surname)))
```
```racket
> (greet "John")
"Hello, John Doe"
> (greet "Adam")
"Hello, Adam Smith"
```
### 4.3. Declaring Keyword Arguments
A `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:
> +Keyword Arguments introduces function calls with keywords.
```racket
(lambda gen-formals
body ...+)
gen-formals = (arg ...)
| rest-id
| (arg ...+ . rest-id)
arg = arg-id
| [arg-id default-expr]
| arg-keyword arg-id
| arg-keyword [arg-id default-expr]
```
An argument specified as `arg-keyword arg-id` is supplied by an
application using the same `arg-keyword`. The position of the
keywordidentifier 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.
```racket
(define greet
(lambda (given #:last surname)
(string-append "Hello, " given " " surname)))
```
```racket
> (greet "John" #:last "Smith")
"Hello, John Smith"
> (greet #:last "Doe" "John")
"Hello, John Doe"
```
An `arg-keyword [arg-id default-expr]` argument specifies a
keyword-based argument with a default value.
Examples:
```racket
(define greet
(lambda (#:hi [hi "Hello"] given #:last [surname "Smith"])
(string-append hi ", " given " " surname)))
> (greet "John")
"Hello, John Smith"
> (greet "Karl" #:last "Marx")
"Hello, Karl Marx"
> (greet "John" #:hi "Howdy")
"Howdy, John Smith"
> (greet "Karl" #:last "Marx" #:hi "Guten Tag")
"Guten Tag, Karl Marx"
```
The `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 `make-keyword-procedure`. The function supplied
to `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.
> +The `apply` Function introduces `keyword-apply`.
Examples:
```racket
(define (trace-wrap f)
(make-keyword-procedure
(lambda (kws kw-args . rest)
(printf "Called with ~s ~s ~s\n" kws kw-args rest)
(keyword-apply f kws kw-args rest))))
> ((trace-wrap greet) "John" #:hi "Howdy")
Called with (#:hi) ("Howdy") ("John")
"Howdy, John Smith"
```
> +\[missing\] in \[missing\] provides more on function expressions.
### 4.4. Arity-Sensitive Functions: `case-lambda`
The `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
```racket
(case-lambda
[formals body ...+]
...)
formals = (arg-id ...)
| rest-id
| (arg-id ...+ . rest-id)
```
where each `[formals body ...+]` is analogous to `(lambda formals body
...+)`. Applying a function produced by `case-lambda` is like applying a
`lambda` for the first case that matches the number of given arguments.
Examples:
```racket
(define greet
(case-lambda
[(name) (string-append "Hello, " name)]
[(given surname) (string-append "Hello, " given " " surname)]))
> (greet "John")
"Hello, John"
> (greet "John" "Smith")
"Hello, John Smith"
> (greet)
greet: arity mismatch;
the expected number of arguments does not match the given
number
given: 0
```
A `case-lambda` function cannot directly support optional or keyword
arguments.
## 5. Definitions: `define`
A basic definition has the form
```racket
(define id expr)
```
in which case `id` is bound to the result of `expr`.
Examples:
```racket
(define salutation (list-ref '("Hi" "Hello") (random 2)))
> salutation
"Hello"
```
### 5.1. Function Shorthand
The `define` form also supports a shorthand for function definitions:
```racket
(define (id arg ...) body ...+)
```
which is a shorthand for
`(define` `id` `(lambda` `(arg` `...)` `body` `...+))`
Examples:
```racket
(define (greet name)
(string-append salutation ", " name))
> (greet "John")
"Hello, John"
```
```racket
(define (greet first [surname "Smith"] #:hi [hi salutation])
(string-append hi ", " first " " surname))
```
```racket
> (greet "John")
"Hello, John Smith"
> (greet "John" #:hi "Hey")
"Hey, John Smith"
> (greet "John" "Doe")
"Hello, John Doe"
```
The function shorthand via `define` also supports a rest argument
\(i.e., a final argument to collect extra arguments in a list\):
```racket
(define (id arg ... . rest-id) body ...+)
```
which is a shorthand
`(define` `id` `(lambda` `(arg` `...` `. rest-id)` `body` `...+))`
Examples:
```racket
(define (avg . l)
(/ (apply + l) (length l)))
> (avg 1 2 3)
2
```
### 5.2. Curried Function Shorthand
Consider the following `make-add-suffix` function that takes a string
and returns another function that takes a string:
```racket
(define make-add-suffix
(lambda (s2)
(lambda (s) (string-append s s2))))
```
Although its not common, result of `make-add-suffix` could be called
directly, like this:
```racket
> ((make-add-suffix "!") "hello")
"hello!"
```
In a sense, `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 _curried
function_.
Using the function-shorthand form of `define`, `make-add-suffix` can be
written equivalently as
```racket
(define (make-add-suffix s2)
(lambda (s) (string-append s s2)))
```
This shorthand reflects the shape of the function call `(make-add-suffix
"!")`. The `define` form further supports a shorthand for defining
curried functions that reflects nested function calls:
```racket
(define ((make-add-suffix s2) s)
(string-append s s2))
```
```racket
> ((make-add-suffix "!") "hello")
"hello!"
```
```racket
(define louder (make-add-suffix "!"))
(define less-sure (make-add-suffix "?"))
```
```racket
> (less-sure "really")
"really?"
> (louder "really")
"really!"
```
The full syntax of the function shorthand for `define` is as follows:
```racket
(define (head args) body ...+)
head = id
| (head args)
args = arg ...
| arg ... . rest-id
```
The expansion of this shorthand has one nested `lambda` form for each
`head` in the definition, where the innermost `head` corresponds to the
outermost `lambda`.
### 5.3. Multiple Values and `define-values`
A Racket expression normally produces a single result, but some
expressions can produce multiple results. For example, `quotient` and
`remainder` each produce a single value, but `quotient/remainder`
produces the same two values at once:
```racket
> (quotient 13 3)
4
> (remainder 13 3)
1
> (quotient/remainder 13 3)
4
1
```
As shown above, the REPL prints each result value on its own line.
Multiple-valued functions can be implemented in terms of the `values`
function, which takes any number of values and returns them as the
results:
```racket
> (values 1 2 3)
1
2
3
```
```racket
(define (split-name name)
(let ([parts (regexp-split " " name)])
(if (= (length parts) 2)
(values (list-ref parts 0) (list-ref parts 1))
(error "not a <first> <last> name"))))
```
```racket
> (split-name "Adam Smith")
"Adam"
"Smith"
```
The `define-values` form binds multiple identifiers at once to multiple
results produced from a single expression:
```racket
(define-values (id ...) expr)
```
The number of results produced by the `expr` must match the number of
`id`s.
Examples:
```racket
(define-values (given surname) (split-name "Adam Smith"))
> given
"Adam"
> surname
"Smith"
```
A `define` form \(that is not a function shorthand\) is equivalent to a
`define-values` form with a single `id`.
> +\[missing\] in \[missing\] provides more on definitions.
### 5.4. Internal Definitions
When the grammar for a syntactic form specifies `body`, then the
corresponding form can be either a definition or an expression. A
definition as a `body` is an _internal definition_.
Expressions and internal definitions in a `body` sequence can be mixed,
as long as the last `body` is an expression.
For example, the syntax of `lambda` is
```racket
(lambda gen-formals
body ...+)
```
so the following are valid instances of the grammar:
```racket
(lambda (f) ; no definitions
(printf "running\n")
(f 0))
(lambda (f) ; one definition
(define (log-it what)
(printf "~a\n" what))
(log-it "running")
(f 0)
(log-it "done"))
(lambda (f n) ; two definitions
(define (call n)
(if (zero? n)
(log-it "done")
(begin
(log-it "running")
(f n)
(call (- n 1)))))
(define (log-it what)
(printf "~a\n" what))
(call n))
```
Internal definitions in a particular `body` sequence are mutually
recursive; that is, any definition can refer to any other definition—as
long as the reference isnt actually evaluated before its definition
takes place. If a definition is referenced too early, an error occurs.
Examples:
```racket
(define (weird)
(define x x)
x)
> (weird)
x: undefined;
cannot use before initialization
```
A sequence of internal definitions using just `define` is easily
translated to an equivalent `letrec` form \(as introduced in the next
section\). However, other definition forms can appear as a `body`,
including `define-values`, `struct` \(see \[missing\]\) or
`define-syntax` \(see \[missing\]\).
> +\[missing\] in \[missing\] documents the fine points of internal
> definitions.
## 6. Local Binding
Although internal `define`s can be used for local binding, Racket
provides three forms that give the programmer more control over
bindings: `let`, `let*`, and `letrec`.
### 6.1. Parallel Binding: `let`
> +\[missing\] in \[missing\] also documents `let`.
A `let` form binds a set of identifiers, each to the result of some
expression, for use in the `let` body:
```racket
(let ([id expr] ...) body ...+)
```
The `id`s are bound “in parallel.” That is, no `id` is bound in the
right-hand side `expr` for any `id`, but all are available in the
`body`. The `id`s must be different from each other.
Examples:
```racket
> (let ([me "Bob"])
me)
"Bob"
> (let ([me "Bob"]
[myself "Robert"]
[I "Bobby"])
(list me myself I))
'("Bob" "Robert" "Bobby")
> (let ([me "Bob"]
[me "Robert"])
me)
eval:3:0: let: duplicate identifier
at: me
in: (let ((me "Bob") (me "Robert")) me)
```
The fact that an `id`s `expr` does not see its own binding is often
useful for wrappers that must refer back to the old value:
```racket
> (let ([+ (lambda (x y)
(if (string? x)
(string-append x y)
(+ x y)))]) ; use original +
(list (+ 1 2)
(+ "see" "saw")))
'(3 "seesaw")
```
Occasionally, the parallel nature of `let` bindings is convenient for
swapping or rearranging a set of bindings:
```racket
> (let ([me "Tarzan"]
[you "Jane"])
(let ([me you]
[you me])
(list me you)))
'("Jane" "Tarzan")
```
The characterization of `let` bindings as “parallel” is not meant to
imply concurrent evaluation. The `expr`s are evaluated in order, even
though the bindings are delayed until all `expr`s are evaluated.
### 6.2. Sequential Binding: `let*`
> +\[missing\] in \[missing\] also documents `let*`.
The syntax of `let*` is the same as `let`:
```racket
(let* ([id expr] ...) body ...+)
```
The difference is that each `id` is available for use in later `expr`s,
as well as in the `body`. Furthermore, the `id`s need not be distinct,
and the most recent binding is the visible one.
Examples:
```racket
> (let* ([x (list "Burroughs")]
[y (cons "Rice" x)]
[z (cons "Edgar" y)])
(list x y z))
'(("Burroughs") ("Rice" "Burroughs") ("Edgar" "Rice" "Burroughs"))
> (let* ([name (list "Burroughs")]
[name (cons "Rice" name)]
[name (cons "Edgar" name)])
name)
'("Edgar" "Rice" "Burroughs")
```
In other words, a `let*` form is equivalent to nested `let` forms, each
with a single binding:
```racket
> (let ([name (list "Burroughs")])
(let ([name (cons "Rice" name)])
(let ([name (cons "Edgar" name)])
name)))
'("Edgar" "Rice" "Burroughs")
```
### 6.3. Recursive Binding: `letrec`
> +\[missing\] in \[missing\] also documents `letrec`.
The syntax of `letrec` is also the same as `let`:
```racket
(letrec ([id expr] ...) body ...+)
```
While `let` makes its bindings available only in the `body`s, and `let*`
makes its bindings available to any later binding `expr`, `letrec` makes
its bindings available to all other `expr`s—even earlier ones. In other
words, `letrec` bindings are recursive.
The `expr`s in a `letrec` form are most often `lambda` forms for
recursive and mutually recursive functions:
```racket
> (letrec ([swing
(lambda (t)
(if (eq? (car t) 'tarzan)
(cons 'vine
(cons 'tarzan (cddr t)))
(cons (car t)
(swing (cdr t)))))])
(swing '(vine tarzan vine vine)))
'(vine vine tarzan vine)
```
```racket
> (letrec ([tarzan-near-top-of-tree?
(lambda (name path depth)
(or (equal? name "tarzan")
(and (directory-exists? path)
(tarzan-in-directory? path depth))))]
[tarzan-in-directory?
(lambda (dir depth)
(cond
[(zero? depth) #f]
[else
(ormap
(λ (elem)
(tarzan-near-top-of-tree? (path-element->string elem)
(build-path dir elem)
(- depth 1)))
(directory-list dir))]))])
(tarzan-near-top-of-tree? "tmp"
(find-system-path 'temp-dir)
4))
#f
```
While the `expr`s of a `letrec` form are typically `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 `id`. If an `id` is referenced before its value is ready,
an error is raised, just as for internal definitions.
```racket
> (letrec ([quicksand quicksand])
quicksand)
quicksand: undefined;
cannot use before initialization
```
### 6.4. Named `let`
A named `let` is an iteration and recursion form. It uses the same
syntactic keyword `let` as for local binding, but an identifier after
the `let` \(instead of an immediate open parenthesis\) triggers a
different parsing.
```racket
(let proc-id ([arg-id init-expr] ...)
body ...+)
```
A named `let` form is equivalent to
```racket
(letrec ([proc-id (lambda (arg-id ...)
body ...+)])
(proc-id init-expr ...))
```
That is, a named `let` binds a function identifier that is visible only
in the functions body, and it implicitly calls the function with the
values of some initial expressions.
Examples:
```racket
(define (duplicate pos lst)
(let dup ([i 0]
[lst lst])
(cond
[(= i pos) (cons (car lst) lst)]
[else (cons (car lst) (dup (+ i 1) (cdr lst)))])))
> (duplicate 1 (list "apple" "cheese burger!" "banana"))
'("apple" "cheese burger!" "cheese burger!" "banana")
```
### 6.5. Multiple Values: `let-values`, `let*-values`, `letrec-values`
> +\[missing\] in \[missing\] also documents multiple-value binding forms.
In the same way that `define-values` binds multiple results in a
definition \(see Multiple Values and `define-values`\), `let-values`,
`let*-values`, and `letrec-values` bind multiple results locally.
```racket
(let-values ([(id ...) expr] ...)
body ...+)
```
```racket
(let*-values ([(id ...) expr] ...)
body ...+)
```
```racket
(letrec-values ([(id ...) expr] ...)
body ...+)
```
Each `expr` must produce as many values as corresponding `id`s. The
binding rules are the same for the forms without `-values` forms: the
`id`s of `let-values` are bound only in the `body`s, the `id`s of
`let*-values`s are bound in `expr`s of later clauses, and the `id`s of
`letrec-value`s are bound for all `expr`s.
Example:
```racket
> (let-values ([(q r) (quotient/remainder 14 3)])
(list q r))
'(4 2)
```
## 7. Conditionals
Most functions used for branching, such as `<` and `string?`, produce
either `#t` or `#f`. Rackets branching forms, however, treat any value
other than `#f` as true. We say a _true value_ to mean any value other
than `#f`.
This convention for “true value” meshes well with protocols where `#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 `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:
```racket
> (member "Groucho" '("Harpo" "Zeppo"))
#f
> (member "Groucho" '("Harpo" "Groucho" "Zeppo"))
'("Groucho" "Zeppo")
> (if (member "Groucho" '("Harpo" "Zeppo"))
'yep
'nope)
'nope
> (if (member "Groucho" '("Harpo" "Groucho" "Zeppo"))
'yep
'nope)
'yep
```
### 7.1. Simple Branching: `if`
> +\[missing\] in \[missing\] also documents `if`.
In an `if` form,
```racket
(if test-expr then-expr else-expr)
```
the `test-expr` is always evaluated. If it produces any value other than
`#f`, then `then-expr` is evaluated. Otherwise, `else-expr` is
evaluated.
An `if` form must have both a `then-expr` and an `else-expr`; the latter
is not optional. To perform \(or skip\) side-effects based on a
`test-expr`, use `when` or `unless`, which we describe later in
Sequencing.
### 7.2. Combining Tests: `and` and `or`
> +\[missing\] in \[missing\] also documents `and` and `or`.
Rackets `and` and `or` are syntactic forms, rather than functions.
Unlike a function, the `and` and `or` forms can skip evaluation of later
expressions if an earlier one determines the answer.
```racket
(and expr ...)
```
An `and` form produces `#f` if any of its `expr`s produces `#f`.
Otherwise, it produces the value of its last `expr`. As a special case,
`(and)` produces `#t`.
```racket
(or expr ...)
```
The `or` form produces `#f` if all of its `expr`s produce `#f`.
Otherwise, it produces the first non-`#f` value from its `expr`s. As a
special case, `(or)` produces `#f`.
Examples:
```racket
> (define (got-milk? lst)
(and (not (null? lst))
(or (eq? 'milk (car lst))
(got-milk? (cdr lst))))) ; recurs only if needed
> (got-milk? '(apple banana))
#f
> (got-milk? '(apple milk banana))
#t
```
If evaluation reaches the last `expr` of an `and` or `or` form, then the
`expr`s value directly determines the `and` or `or` result. Therefore,
the last `expr` is in tail position, which means that the above
`got-milk?` function runs in constant space.
> +\[missing\] introduces tail calls and tail positions.
### 7.3. Chaining Tests: `cond`
The `cond` form chains a series of tests to select a result expression.
To a first approximation, the syntax of `cond` is as follows:
> +\[missing\] in \[missing\] also documents `cond`.
```racket
(cond [test-expr body ...+]
...)
```
Each `test-expr` is evaluated in order. If it produces `#f`, the
corresponding `body`s are ignored, and evaluation proceeds to the next
`test-expr`. As soon as a `test-expr` produces a true value, its `body`s
are evaluated to produce the result for the `cond` form, and no further
`test-expr`s are evaluated.
The last `test-expr` in a `cond` can be replaced by `else`. In terms of
evaluation, `else` serves as a synonym for `#t`, but it clarifies that
the last clause is meant to catch all remaining cases. If `else` is not
used, then it is possible that no `test-expr`s produce a true value; in
that case, the result of the `cond` expression is `#<void>`.
Examples:
```racket
> (cond
[(= 2 3) (error "wrong!")]
[(= 2 2) 'ok])
'ok
> (cond
[(= 2 3) (error "wrong!")])
> (cond
[(= 2 3) (error "wrong!")]
[else 'ok])
'ok
```
```racket
(define (got-milk? lst)
(cond
[(null? lst) #f]
[(eq? 'milk (car lst)) #t]
[else (got-milk? (cdr lst))]))
```
```racket
> (got-milk? '(apple banana))
#f
> (got-milk? '(apple milk banana))
#t
```
The full syntax of `cond` includes two more kinds of clauses:
```racket
(cond cond-clause ...)
cond-clause = [test-expr then-body ...+]
| [else then-body ...+]
| [test-expr => proc-expr]
| [test-expr]
```
The `=>` variant captures the true result of its `test-expr` and passes
it to the result of the `proc-expr`, which must be a function of one
argument.
Examples:
```racket
> (define (after-groucho lst)
(cond
[(member "Groucho" lst) => cdr]
[else (error "not there")]))
> (after-groucho '("Harpo" "Groucho" "Zeppo"))
'("Zeppo")
> (after-groucho '("Harpo" "Zeppo"))
not there
```
A clause that includes only a `test-expr` is rarely used. It captures
the true result of the `test-expr`, and simply returns the result for
the whole `cond` expression.
## 8. Sequencing
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.
### 8.1. Effects Before: `begin`
> +\[missing\] in \[missing\] also documents `begin`.
A `begin` expression sequences expressions:
```racket
(begin expr ...+)
```
The `expr`s are evaluated in order, and the result of all but the last
`expr` is ignored. The result from the last `expr` is the result of the
`begin` form, and it is in tail position with respect to the `begin`
form.
Examples:
```racket
(define (print-triangle height)
(if (zero? height)
(void)
(begin
(display (make-string height #\*))
(newline)
(print-triangle (sub1 height)))))
> (print-triangle 4)
****
***
**
*
```
Many forms, such as `lambda` or `cond` support a sequence of expressions
even without a `begin`. Such positions are sometimes said to have an
_implicit begin_.
Examples:
```racket
(define (print-triangle height)
(cond
[(positive? height)
(display (make-string height #\*))
(newline)
(print-triangle (sub1 height))]))
> (print-triangle 4)
****
***
**
*
```
The `begin` form is special at the top level, at module level, or as a
`body` after only internal definitions. In those positions, instead of
forming an expression, the content of `begin` is spliced into the
surrounding context.
Example:
```racket
> (let ([curly 0])
(begin
(define moe (+ 1 curly))
(define larry (+ 1 moe)))
(list larry curly moe))
'(2 0 1)
```
This splicing behavior is mainly useful for macros, as we discuss later
in \[missing\].
### 8.2. Effects After: `begin0`
> +\[missing\] in \[missing\] also documents `begin0`.
A `begin0` expression has the same syntax as a `begin` expression:
```racket
(begin0 expr ...+)
```
The difference is that `begin0` returns the result of the first `expr`,
instead of the result of the last `expr`. The `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.
Examples:
```racket
(define (log-times thunk)
(printf "Start: ~s\n" (current-inexact-milliseconds))
(begin0
(thunk)
(printf "End..: ~s\n" (current-inexact-milliseconds))))
> (log-times (lambda () (sleep 0.1) 0))
Start: 1548117365804.718
End..: 1548117365906.647
0
> (log-times (lambda () (values 1 2)))
Start: 1548117365907.178
End..: 1548117365907.202
1
2
```
### 8.3. Effects If...: `when` and `unless`
> +\[missing\] in \[missing\] also documents `when` and `unless`.
The `when` form combines an `if`-style conditional with sequencing for
the “then” clause and no “else” clause:
```racket
(when test-expr then-body ...+)
```
If `test-expr` produces a true value, then all of the `then-body`s are
evaluated. The result of the last `then-body` is the result of the
`when` form. Otherwise, no `then-body`s are evaluated and the result is
`#<void>`.
The `unless` form is similar:
```racket
(unless test-expr then-body ...+)
```
The difference is that the `test-expr` result is inverted: the
`then-body`s are evaluated only if the `test-expr` result is `#f`.
Examples:
```racket
(define (enumerate lst)
(if (null? (cdr lst))
(printf "~a.\n" (car lst))
(begin
(printf "~a, " (car lst))
(when (null? (cdr (cdr lst)))
(printf "and "))
(enumerate (cdr lst)))))
> (enumerate '("Larry" "Curly" "Moe"))
Larry, Curly, and Moe.
```
```racket
(define (print-triangle height)
(unless (zero? height)
(display (make-string height #\*))
(newline)
(print-triangle (sub1 height))))
```
```racket
> (print-triangle 4)
****
***
**
*
```
## 9. Assignment: `set!`
> +\[missing\] in \[missing\] also documents `set!`.
Assign to a variable using `set!`:
```racket
(set! id expr)
```
A `set!` expression evaluates `expr` and changes `id` \(which must be
bound in the enclosing environment\) to the resulting value. The result
of the `set!` expression itself is `#<void>`.
Examples:
```racket
(define greeted null)
(define (greet name)
(set! greeted (cons name greeted))
(string-append "Hello, " name))
> (greet "Athos")
"Hello, Athos"
> (greet "Porthos")
"Hello, Porthos"
> (greet "Aramis")
"Hello, Aramis"
> greeted
'("Aramis" "Porthos" "Athos")
```
```racket
(define (make-running-total)
(let ([n 0])
(lambda ()
(set! n (+ n 1))
n)))
(define win (make-running-total))
(define lose (make-running-total))
```
```racket
> (win)
1
> (win)
2
> (lose)
1
> (win)
3
```
### 9.1. Guidelines for Using Assignment
Although using `set!` is sometimes appropriate, Racket style generally
discourages the use of `set!`. The following guidelines may help explain
when using `set!` is appropriate.
* As in any modern language, assigning to a shared identifier is no
substitute for passing an argument to a procedure or getting its
result.
**_Really awful_** example:
```racket
(define name "unknown")
(define result "unknown")
(define (greet)
(set! result (string-append "Hello, " name)))
```
```racket
> (set! name "John")
> (greet)
> result
"Hello, John"
```
Ok example:
```racket
(define (greet name)
(string-append "Hello, " name))
```
```racket
> (greet "John")
"Hello, John"
> (greet "Anna")
"Hello, Anna"
```
* A sequence of assignments to a local variable is far inferior to
nested bindings.
**Bad** example:
```racket
> (let ([tree 0])
(set! tree (list tree 1 tree))
(set! tree (list tree 2 tree))
(set! tree (list tree 3 tree))
tree)
'(((0 1 0) 2 (0 1 0)) 3 ((0 1 0) 2 (0 1 0)))
```
Ok example:
```racket
> (let* ([tree 0]
[tree (list tree 1 tree)]
[tree (list tree 2 tree)]
[tree (list tree 3 tree)])
tree)
'(((0 1 0) 2 (0 1 0)) 3 ((0 1 0) 2 (0 1 0)))
```
* Using assignment to accumulate results from an iteration is bad style.
Accumulating through a loop argument is better.
Somewhat bad example:
```racket
(define (sum lst)
(let ([s 0])
(for-each (lambda (i) (set! s (+ i s)))
lst)
s))
```
```racket
> (sum '(1 2 3))
6
```
Ok example:
```racket
(define (sum lst)
(let loop ([lst lst] [s 0])
(if (null? lst)
s
(loop (cdr lst) (+ s (car lst))))))
```
```racket
> (sum '(1 2 3))
6
```
Better \(use an existing function\) example:
```racket
(define (sum lst)
(apply + lst))
```
```racket
> (sum '(1 2 3))
6
```
Good \(a general approach\) example:
```racket
(define (sum lst)
(for/fold ([s 0])
([i (in-list lst)])
(+ s i)))
```
```racket
> (sum '(1 2 3))
6
```
* For cases where stateful objects are necessary or appropriate, then
implementing the objects state with `set!` is fine.
Ok example:
```racket
(define next-number!
(let ([n 0])
(lambda ()
(set! n (add1 n))
n)))
```
```racket
> (next-number!)
1
> (next-number!)
2
> (next-number!)
3
```
All else being equal, a program that uses no assignments or mutation is
always preferable to one that uses assignments or mutation. While side
effects are to be avoided, however, they should be used if the 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 `set!` directly.
Nevertheless, simply replacing `set!`s in a program with `vector-set!`s
obviously does not improve the style of the program.
### 9.2. Multiple Values: `set!-values`
> +\[missing\] in \[missing\] also documents `set!-values`.
The `set!-values` form assigns to multiple variables at once, given an
expression that produces an appropriate number of values:
```racket
(set!-values (id ...) expr)
```
This form is equivalent to using `let-values` to receive multiple
results from `expr`, and then assigning the results individually to the
`id`s using `set!`.
Examples:
```racket
(define game
(let ([w 0]
[l 0])
(lambda (win?)
(if win?
(set! w (+ w 1))
(set! l (+ l 1)))
(begin0
(values w l)
; swap sides...
(set!-values (w l) (values l w))))))
> (game #t)
1
0
> (game #t)
1
1
> (game #f)
1
2
```
## 10. Quoting: `quote` and `'`
> +\[missing\] in \[missing\] also documents `quote`.
The `quote` form produces a constant:
```racket
(quote datum)
```
The syntax of a `datum` is technically specified as anything that the
`read` function parses as a single element. The value of the `quote`
form is the same value that `read` would produce given `datum`.
The `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:
```racket
> (quote apple)
'apple
> (quote #t)
#t
> (quote 42)
42
> (quote "hello")
"hello"
> (quote ())
'()
> (quote ((1 2 3) #("z" x) . the-end))
'((1 2 3) #("z" x) . the-end)
> (quote (1 2 . (3)))
'(1 2 3)
```
As the last example above shows, the `datum` does not have to match the
normalized printed form of a value. A `datum` cannot be a printed
representation that starts with `#<`, so it cannot be `#<void>`,
`#<undefined>`, or a procedure.
The `quote` form is rarely used for a `datum` that is a boolean, number,
or string by itself, since the printed forms of those values can already
be used as constants. The `quote` form is more typically used for
symbols and lists, which have other meanings \(identifiers, function
calls, etc.\) when not quoted.
An expression
```racket
'datum
```
is a shorthand for
`(quote` `datum)`
and this shorthand is almost always used instead of `quote`. The
shorthand applies even within the `datum`, so it can produce a list
containing `quote`.
> +\[missing\] in \[missing\] provides more on the `'` shorthand.
Examples:
```racket
> 'apple
'apple
> '"hello"
"hello"
> '(1 2 3)
'(1 2 3)
> (display '(you can 'me))
(you can (quote me))
```
## 11. Quasiquoting: `quasiquote` and ``
> +\[missing\] in \[missing\] also documents `quasiquote`.
The `quasiquote` form is similar to `quote`:
```racket
(quasiquote datum)
```
However, for each `(unquote expr)` that appears within the `datum`, the
`expr` is evaluated to produce a value that takes the place of the
`unquote` sub-form.
Example:
```racket
> (quasiquote (1 2 (unquote (+ 1 2)) (unquote (- 5 1))))
'(1 2 3 4)
```
This form can be used to write functions that build lists according to
certain patterns.
Examples:
```racket
> (define (deep n)
(cond
[(zero? n) 0]
[else
(quasiquote ((unquote n) (unquote (deep (- n 1)))))]))
> (deep 8)
'(8 (7 (6 (5 (4 (3 (2 (1 0))))))))
```
Or even to cheaply construct expressions programmatically. \(Of course,
9 times out of 10, you should be using a macro to do this \(the 10th
time being when youre working through a textbook like
[PLAI](http://www.cs.brown.edu/~sk/Publications/Books/ProgLangs/)\).\)
Examples:
```racket
> (define (build-exp n)
(add-lets n (make-sum n)))
> (define (add-lets n body)
(cond
[(zero? n) body]
[else
(quasiquote
(let ([(unquote (n->var n)) (unquote n)])
(unquote (add-lets (- n 1) body))))]))
> (define (make-sum n)
(cond
[(= n 1) (n->var 1)]
[else
(quasiquote (+ (unquote (n->var n))
(unquote (make-sum (- n 1)))))]))
> (define (n->var n) (string->symbol (format "x~a" n)))
> (build-exp 3)
'(let ((x3 3)) (let ((x2 2)) (let ((x1 1)) (+ x3 (+ x2 x1)))))
```
The `unquote-splicing` form is similar to `unquote`, but its `expr` must
produce a list, and the `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.
Example:
```racket
> (quasiquote (1 2 (unquote-splicing (list (+ 1 2) (- 5 1))) 5))
'(1 2 3 4 5)
```
Using splicing we can revise the construction of our example expressions
above to have just a single `let` expression and a single `+`
expression.
Examples:
```racket
> (define (build-exp n)
(add-lets
n
(quasiquote (+ (unquote-splicing
(build-list
n
(λ (x) (n->var (+ x 1)))))))))
> (define (add-lets n body)
(quasiquote
(let (unquote
(build-list
n
(λ (n)
(quasiquote
[(unquote (n->var (+ n 1))) (unquote (+ n 1))]))))
(unquote body))))
> (define (n->var n) (string->symbol (format "x~a" n)))
> (build-exp 3)
'(let ((x1 1) (x2 2) (x3 3)) (+ x1 x2 x3))
```
If a `quasiquote` form appears within an enclosing `quasiquote` form,
then the inner `quasiquote` effectively cancels one layer of `unquote`
and `unquote-splicing` forms, so that a second `unquote` or
`unquote-splicing` is needed.
Examples:
```racket
> (quasiquote (1 2 (quasiquote (unquote (+ 1 2)))))
'(1 2 (quasiquote (unquote (+ 1 2))))
> (quasiquote (1 2 (quasiquote (unquote (unquote (+ 1 2))))))
'(1 2 (quasiquote (unquote 3)))
>
(quasiquote (1 2 (quasiquote ((unquote (+ 1 2)) (unquote (unquote (- 5 1)))))))
'(1 2 (quasiquote ((unquote (+ 1 2)) (unquote 4))))
```
The evaluations above will not actually print as shown. Instead, the
shorthand form of `quasiquote` and `unquote` will be used: ` \(i.e., a
backquote\) and `,` \(i.e., a comma\). The same shorthands can be used
in expressions:
Example:
```racket
> `(1 2 `(,(+ 1 2) ,,(- 5 1)))
'(1 2 `(,(+ 1 2) ,4))
```
The shorthand form of `unquote-splicing` is `,@`:
Example:
```racket
> `(1 2 ,@(list (+ 1 2) (- 5 1)))
'(1 2 3 4)
```
## 12. Simple Dispatch: `case`
The `case` form dispatches to a clause by matching the result of an
expression to the values for the clause:
```racket
(case expr
[(datum ...+) body ...+]
...)
```
Each `datum` will be compared to the result of `expr` using `equal?`,
and then the corresponding `body`s are evaluated. The `case` form can
dispatch to the correct clause in _O_\(_log N_\)__ time for _N_
`datum`s.
Multiple `datum`s can be supplied for each clause, and the corresponding
`body`s are evaluated if any of the `datum`s match.
Example:
```racket
> (let ([v (random 6)])
(printf "~a\n" v)
(case v
[(0) 'zero]
[(1) 'one]
[(2) 'two]
[(3 4 5) 'many]))
2
'two
```
The last clause of a `case` form can use `else`, just like `cond`:
Example:
```racket
> (case (random 6)
[(0) 'zero]
[(1) 'one]
[(2) 'two]
[else 'many])
'two
```
For more general pattern matching \(but without the dispatch-time
guarantee\), use `match`, which is introduced in \[missing\].
## 13. Dynamic Binding: `parameterize`
> +\[missing\] in \[missing\] also documents `parameterize`.
The `parameterize` form associates a new value with a _parameter_ during
the evaluation of `body` expressions:
```racket
(parameterize ([parameter-expr value-expr] ...)
body ...+)
```
> 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.
For example, the `error-print-width` parameter controls how many
characters of a value are printed in an error message:
```racket
> (parameterize ([error-print-width 5])
(car (expt 10 1024)))
car: contract violation
expected: pair?
given: 10...
> (parameterize ([error-print-width 10])
(car (expt 10 1024)))
car: contract violation
expected: pair?
given: 1000000...
```
More generally, parameters implement a kind of dynamic binding. The
`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:
```racket
> (define location (make-parameter "here"))
> (location)
"here"
```
In a `parameterize` form, each `parameter-expr` must produce a
parameter. During the evaluation of the `body`s, each specified
parameter is given the result of the corresponding `value-expr`. When
control leaves the `parameterize` form—either through a normal return,
an exception, or some other escape—the parameter reverts to its earlier
value:
```racket
> (parameterize ([location "there"])
(location))
"there"
> (location)
"here"
> (parameterize ([location "in a house"])
(list (location)
(parameterize ([location "with a mouse"])
(location))
(location)))
'("in a house" "with a mouse" "in a house")
> (parameterize ([location "in a box"])
(car (location)))
car: contract violation
expected: pair?
given: "in a box"
> (location)
"here"
```
The `parameterize` form is not a binding form like `let`; each use of
`location` above refers directly to the original definition. A
`parameterize` form adjusts the value of a parameter during the whole
time that the `parameterize` body is evaluated, even for uses of the
parameter that are textually outside of the `parameterize` body:
```racket
> (define (would-you-could-you?)
(and (not (equal? (location) "here"))
(not (equal? (location) "there"))))
> (would-you-could-you?)
#f
> (parameterize ([location "on a bus"])
(would-you-could-you?))
#t
```
If a use of a parameter is textually inside the body of a `parameterize`
but not evaluated before the `parameterize` form produces a value, then
the use does not see the value installed by the `parameterize` form:
```racket
> (let ([get (parameterize ([location "with a fox"])
(lambda () (location)))])
(get))
"here"
```
The current binding of a parameter can be adjusted imperatively by
calling the parameter as a function with a value. If a `parameterize`
has adjusted the value of the parameter, then directly applying the
parameter procedure affects only the value associated with the active
`parameterize`:
```racket
> (define (try-again! where)
(location where))
> (location)
"here"
> (parameterize ([location "on a train"])
(list (location)
(begin (try-again! "in a boat")
(location))))
'("on a train" "in a boat")
> (location)
"here"
```
Using `parameterize` is generally preferable to updating a parameter
value imperatively—for much the same reasons that binding a fresh
variable with `let` is preferable to using `set!` \(see Assignment:
`set!`\).
It may seem that variables and `set!` can solve many of the same
problems that parameters solve. For example, `lokation` could be defined
as a string, and `set!` could be used to adjust its value:
```racket
> (define lokation "here")
> (define (would-ya-could-ya?)
(and (not (equal? lokation "here"))
(not (equal? lokation "there"))))
> (set! lokation "on a bus")
> (would-ya-could-ya?)
#t
```
Parameters, however, offer several crucial advantages over `set!`:
* The `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 `set!` is relatively tedious.
* Parameters work nicely with tail calls \(see \[missing\]\). The last
`body` in a `parameterize` form is in tail position with respect to
the `parameterize` form.
* Parameters work properly with threads \(see \[missing\]\). The
`parameterize` form adjusts the value of a parameter only for
evaluation in the current thread, which avoids race conditions with
other threads.