# Expressions and Definitions The \[missing\] 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. 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 expression’s _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 module’s 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 Racket’s 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 function’s _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) ; doesn’t work... (/ (+ lst) (length lst))) ``` ```racket > (avg '(1 2 3)) +: contract violation expected: number? given: '(1 2 3) ``` ```racket (define (avg lst) ; doesn’t 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 ((lambda (x) x) 1) 1 > ((lambda (x y) (+ x y)) 1 2) 3 > ((lambda (x y) (+ x y)) 1) #: 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 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. ```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 it’s 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 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 isn’t 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 function’s 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`. Racket’s 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`. Racket’s `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 `#`. 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 `#`. 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 `#`. 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 object’s 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 `#`, `#`, 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 you’re 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.