3 Expressions
An expression can be a literal constant that is a number (type Number), a string (type String), a symbol (type Symbol) written with quote or ', an S-expression (type S-Exp) written with quasiquote or `, #t (type Boolean), #f (type Boolean), or a character (type Char). An expression also can be a bound identifier (in which case its type comes from its binding).
syntax
> (has-type 1 : Number) - Number
1
> (has-type "a" : Number) eval:24:0: typecheck failed: String vs. Number
sources:
"a"
Number
syntax
(quote q-form)
q-form = id | Number | String | Boolean | (q-form ...) | #(q-form ...) | #&q-form
For an introduction, see the tutorial section Lists.
The quote form is usually written as just a ' before a q-form; that is, 'id and (quote id) are equivalent.
The quote form produces a symbol, number, string, boolean, list, vector, or box value:
A quoted id produces a symbol. For example, 'hello produces the symbol whose letters are hello.
A quoted Number, String, or Boolean produces the Number, String, or Boolean itself. For example, '1 is the same as 1.
A quoted parenthesized form produces a list containing the quoted values within the parentheses. For example, '(1 2 3) produces a list containing 1, 2, and 3. Similarly, '(a b c) produces a list containing three symbols, since 'a, 'b, and 'c are symbols.
A quoted #(q-form ...) produces a vector. The vector is immutable, though, so vector-set! will not work on the vector.
A quoted #&q-form produces a box. The box is immutable, though, so set-box! will not work on the box.
Beyond the syntactic contraints of q-form, the resulting list must have a type. So, for example, quote cannot create a list that mixes numbers and symbols.
> 'a - Symbol
'a
> '(1 2 3) - (Listof Number)
'(1 2 3)
> '(1 a) eval:27:0: typecheck failed: Number vs. Symbol
sources:
(quote (1 a))
1
a
> '((a) (b c)) - (Listof (Listof Symbol))
'((a) (b c))
syntax
(quasiquote qq-form)
qq-form = id | Number | String | Boolean | (qq-form ...) | (unquote expr) | (unquote-splicing expr) | (quasiquote expr)
syntax
syntax
For an introduction, see the tutorial section S-Expressions.
The quasiquote form is similar to quote, but it produces an S-expression, and it supports escapes via unquote and unquote-splicing. A (unquote expr) form is replaced with the value of expr, while a (unquote-splicing expr) form requires that expr produces a list and is replaced by the list content as an inlined sequence of S-expressions.
The quasiquote form is usually written as just a ` before qq-form; that is, 'qq-form and (quasiquote qq-form) are equivalent.
The unquote form is usually written as just a , before expr; that is, ,expr and (unquote expr) are equivalent.
The unquote-splicing form is usually written as just a ,@ before expr; that is, ,@expr and (unquote-splicing expr) are equivalent.
With a nested quasiquote form, escapes are preserved while escaping to the enclosing level of quotation. For example, ``(,(+ 1 2)) is equivalent to '(quasiquote (unquote 1)) where the quasiquote and unquote symbols are preserved in the result S-expression.
> `a - S-Exp
`a
> `(1 a) - S-Exp
`(1 a)
> `(+ ,(number->s-exp (+ 1 2)) 3) - S-Exp
`(+ 3 3)
> `(+ ,@(list `1 `2) 3) - S-Exp
`(+ 1 2 3)
syntax
(#%app expr expr ...)
> (add1 1) - Number
2
For an introduction, see the tutorial section Anonymous Functions.
An anonymous function which takes as many argument as specified id/tys and produces the result of expr. Each argument has an optional type specification, and when a type is written after (id/ty ...), it declares the result type of the function.
> (lambda (x) (+ x 1)) - (Number -> Number)
#<procedure>
> (lambda ([x : Number]) (+ x 1)) - (Number -> Number)
#<procedure>
> ((lambda (x) (+ x 1)) 3) - Number
4
> (map (lambda (x) (+ x 1)) (list 1 2 3)) - (Listof Number)
'(2 3 4)
syntax
syntax
(if test-expr expr expr)
syntax
(cond [test-expr expr] ...)
(cond [test-expr expr] ... [else expr])
For an introduction, see the tutorial section Conditionals.
An if form produces the value of the first expr if test-expr produces true or the value of the second expr otherwise. Only one of the two exprs is evaluated.
A cond form produces the value of the first expr whose test-expr produces true. The test-exprs are tried in order until a true result is found, and at most one of the exprs is evaluated. If no test-expr produces a true result, a “no matching clause“ exception is raised. An else in place of the last test-expr is equivalent to #t.
Each test-expr must have type Boolean.
> (if (< 1 2) 'less 'greater-or-equal) - Symbol
'less
> (cond [(< 2 1) 'bad] [(< 2 2) (begin (/ 1 0) 'oops)] [(< 2 3) 'ok] [(< 2 (/ 1 0)) 'oops] [else (begin (/ 1 0) 'oops)]) - Symbol
'ok
syntax
(case val-expr [(id-or-number ...) expr] ...)
(case val-expr [(id-or-number ...) expr] ... [else expr])
The dispatching mode, symbol or number, is inferred from the id-or-numbers, which must all be symbols or numbers for a given use of case. If no clause provides a number or symbol, then symbol dispatch is inferred.
> (case (+ 1 2) [(0 1 2) 'too-small] [(3) 'ok] [else 'other]) - Symbol
'ok
> (case 'goodbye [(hello) 'hi] [(goodbye) 'bye]) - Symbol
'bye
syntax
(begin expr ...+)
For an introduction, see the tutorial section State.
Evaluates the exprs in sequence, producing the result of the last expr.
syntax
(local [definition-or-type-declaration ...] expr)
syntax
(letrec ([id rhs-expr] ...) expr)
syntax
(let ([id rhs-expr] ...) expr)
syntax
(let* ([id rhs-expr] ...) expr)
For an introduction, see the tutorial section Definitions.
Local binding forms. The local form accommodates multiple definitions and type declarations (using :) that are visible only among the definitions and the body expr. The letrec, let, and let* forms bind each id to the value of the corresponding rhs-expr (where the rhs-exprs are evaluated in order). In the case of letrec, each id is visible to every rhs-expr as well as in the body expr. In the case of let, each id is visible only in the body expr. In the case of let*, each id is visible only to later rhs-exprs as well as in the body expr.
> (local [(add-x : (Number -> Number)) (x : Number) (define (add-x y) (+ x y)) (define x 2)] (add-x 3)) - Number
5
> add-x eval:46:0: add-x: free variable while typechecking
in: add-x
> (letrec ([add-x (lambda (y) (+ x y))] [x 2]) (add-x 3)) - Number
5
> (let ([x 1]) (let ([add-x (lambda (y) (+ x y))] [x 2]) (add-x 3))) - Number
4
> (let ([x 1]) (let* ([add-x (lambda (y) (+ x y))] [x 2]) (add-x 3))) - Number
4
> (let ([x 1]) (let* ([x 2] [add-x (lambda (y) (+ x y))]) (add-x 3))) - Number
5
syntax
(shared ([id expr] ...) expr)
syntax
(parameterize ([param-expr val-expr] ...) expr)
> (define current-mode (make-parameter 'straight))
> (define (display-line) (display (case (parameter-ref current-mode) [(straight) "---"] [(curvy) "~~~"])))
> (parameterize ([current-mode 'curvy]) (display-line))
- Void
~~~
> (display-line)
- Void
---
> (define f (parameterize ([current-mode 'curvy]) (lambda () (display-line)))) > (f)
- Void
---
syntax
(set! id expr)
For an introduction, see the tutorial section State.
Mutates id to have the value of expr.
For an introduction, see the tutorial section Conditionals.
Boolean combinations with short-circuiting: as soon as an expr produces false in and or true in or, the remaining exprs are not evaluated. The value of (and) is true and (or) is false. The exprs must have type Boolean.
> (and (< 1 2) (< 3 4)) - Boolean
#t
> (and (< 2 1) (< 3 (/ 1 0))) - Boolean
#f
> (or (< 2 1) (< 3 4)) - Boolean
#t
> (or (< 2 1) (< 1 2) (< 3 (/ 1 0))) - Boolean
#t
syntax
(list elem ...)
For an introduction, see the tutorial section Lists.
Builds a list. All elems must have the same type.
> (list 1 2 3) - (Listof Number)
'(1 2 3)
> (list "a" "b") - (Listof String)
'("a" "b")
> (list (list 1 2) empty (list 3 4)) - (Listof (Listof Number))
'((1 2) () (3 4))
syntax
(vector elem ...)
For an introduction, see the tutorial section State.
Builds a vector. All elems must have the same type.
> (vector 1 2 3) - (Vectorof Number)
'#(1 2 3)
> (vector "a" "b") - (Vectorof String)
'#("a" "b")
> (vector (list 1 2) empty (list 3 4)) - (Vectorof (Listof Number))
'#((1 2) () (3 4))
syntax
(values elem ...)
For an introduction, see the tutorial section Tuples and Options.
Combines multiple values into tuple, where a tuple containing one value is equivalent to the value. Match a tuple result using define-values.
The type of each elem is independent.
> (values 1 'two "three") - (Number * Symbol * String)
(values 1 'two "three")
syntax
(type-case tyid/abs val-expr [(variant-id field-id ...) expr] ...)
(type-case tyid/abs val-expr [(variant-id field-id ...) expr] ... [else expr])
(type-case (Listof type) val-expr [list-variant expr] ...)
(type-case (Listof type) val-expr [list-variant expr] ... [else expr])
tyid/abs = id | (id type ...) list-variant = empty | (cons first-id rest-id)
For an introduction, see the tutorial section Datatypes.
Dispatches based on the variant of the result of val-expr.
In the form that has tyid/abs, val-expr must have type tyid/abs, and tyid/abs must refer to a type defined via define-type. The result is the value of expr for the variant-id that is instantiated by val-expr or the expr in an else clause if no variant-id matches. Each field-id is bound to a corresponding (by position) value of a field within the variant instance for use in the same clause’s expr.
The number of field-ids must match the number of fields declared for variant-id in the definition of tyid/abs, and either every variant-id of tyid/abs must have a clause in the type-case form or an else clause must be present.
> (define-type Shape (circle [radius : Number]) (rectangle [width : Number] [height : Number]))
> (define (area [s : Shape]) (type-case Shape s [(circle r) (* (* r r) 3.14)] [(rectangle w h) (* w h)])) > (area (circle 1)) - Number
3.14
> (area (rectangle 2 3)) - Number
6
In the (Listof type) form, val-expr must have type (Listof type). Each non-else clause is either a (cons first-id rest-id) clause or an empty clause, and both most appear without else, or at most one of those can appear with else.
> (define (my-length l) (type-case (Listof 'a) l [empty 0] [(cons a b) (+ 1 (my-length b))])) > (length '(1 2 3)) - Number
3
> (length '(a b)) - Number
2
> (try 1 (lambda () 2)) - Number
1
> (try (/ 1 0) (lambda () 2)) - Number
2
> (try (begin (error 'demo "oops") 1) (lambda () 2)) - Number
2
> (try (begin (error 'demo "oops") 1) (lambda () (/ 2 0))) - Number
/: division by zero
For an introduction, see the tutorial section Testing and Debugging.
The test form checks whether the value of the first expr matches the value of the second expr, and reports a test failure or success. If the results of the two exprs are numbers and either is inexact, the test passes as long as the difference between the numbers is less than 0.01.
The test/exn form checks whether the expr raises an exception whose error message includes the string produced by string-expr.
The test and test/exn forms have type Void, although they do not actually produce a void value; instead, they produce results suitable for automatic display through a top-level expression, and the Void type merely prevents your program from using the result.
See also print-only-errors and module+.
syntax
(time expr)
syntax
(let/cc id expr)