In an S-expression language a program is a tree of lists, and the first element of a list decides what the list means. If it names a form (also called syntax), the form decides; otherwise the list is a procedure call. This page covers the forms of racket/base that define, bind, branch, sequence and quote. Loops are in Control and loops and procedures in Functions.
Expressions
| Expression | Meaning |
|---|---|
a literal (5, "x", #t, #\a) | evaluates to itself. Racket expands it as (#%datum . 5), so a language can change what literals mean |
| an identifier | the value of the nearest binding. An identifier with no binding is an error at compile time in a module (unbound identifier); at the top level, it is an error when evaluated |
(proc arg …) | application: evaluates proc and the arguments left to right, then calls the procedure. Racket expands it as (#%app proc arg …). A keyword before an argument passes it by name: (f #:size 3 x). Calling a non-procedure, or a procedure with the wrong number of arguments or a missing required keyword, raises exn:fail:contract |
(quote d) or 'd | the datum d, not evaluated |
(quasiquote d) or `d | a datum in which ,e and ,@e are evaluated; see below |
(#%expression e) | marks e as an expression (not a definition) where either could stand |
(#%top . id) | the reference to an unbound identifier; a language can change what it does |
(#%variable-reference id) | a handle on the location of a variable, for tools |
Definitions
| Form | Effect |
|---|---|
(define id expr) | binds id to the value of expr |
(define (id arg …) body …+) | binds id to a procedure; shorthand for (define id (lambda (arg …) body …)). (define ((f a) b) …) is curried: it defines f as a procedure that returns a procedure |
(define (id . rest) …), (define (id a [b 1] #:k k) …) | rest, optional and keyword arguments; see Functions |
(define-values (id …) expr) | binds several identifiers to the several results of expr; the number must match |
(define-syntax id expr), (define-syntax (id stx) body …) | binds id as a macro; see Macros |
(define-syntax-rule (id pattern …) template) | a macro with one pattern |
(define-syntaxes (id …) expr) | several macros at once |
(define-for-syntax …), (define-values-for-syntax …) | definitions that exist at compile time, for use in macros |
(define-inline (id arg …) body) | a function that the compiler is asked to inline at every use |
(struct …), (define-struct …) | define a structure type and its procedures; see Structs |
In a module, every name defined at the module level is visible in the whole module: functions may use each other, but a value must be defined before a definition's expression runs and uses it. Definitions are not allowed where only an expression stands, such as an if branch. They are allowed in an internal-definition context: the body of lambda, let, when, unless, cond and case clauses, and begin inside one of those. There the definitions are mutually recursive, as in letrec, and expressions and definitions can alternate. The last form must be an expression.
Local binding
| Form | Meaning |
|---|---|
(let ([id expr] …) body …+) | binds the ids to the values of the exprs, which are evaluated outside the new scope, left to right |
(let loop ([id expr] …) body …+) | named let: also binds loop to a procedure of the ids, so the body can repeat by calling it; a call in tail position is a loop |
(let* ([id expr] …) body …+) | each binding sees the earlier ones |
(letrec ([id expr] …) body …+) | all bindings see each other, for mutual recursion; an id used before it is set raises an error |
(let-values ([(id …) expr] …) body …+), let*-values, letrec-values | bind the several values an expression returns; [(a b) (values 1 2)] |
(let-syntax …), letrec-syntax, let-syntaxes, letrec-syntaxes+values | local macros |
(local [definition …] body …+) | racket/local: definitions that scope over the body, like internal definitions |
(let/ec k body …), (let/cc k body …) | bind k to an escape or full continuation; see Control and loops |
(with-syntax ([pattern expr] …) body) | binds pattern variables for use in #' templates |
(parameterize ([param expr] …) body …+) | binds the value of parameters for the dynamic extent of the body |
The bracket shape is a habit, not a rule: (let ((x 1) (y 2)) …) and (let ([x 1] [y 2]) …) read the same.
#lang racket
(define (distance x1 y1 x2 y2)
(define dx (- x2 x1)) ; internal definitions
(define dy (- y2 y1))
(sqrt (+ (* dx dx) (* dy dy))))
(let loop ([i 0] [acc '()]) ; named let
(if (= i 3)
(reverse acc)
(loop (add1 i) (cons i acc)))) ; => '(0 1 2)
(let-values ([(q r) (quotient/remainder 17 5)])
(list q r)) ; => '(3 2)
Assignment
(set! id expr) changes a variable that is already bound, and returns void. (set!-values (id …) expr) assigns several. A module cannot set! a variable it imports. Racket style prefers new bindings and immutable data to assignment.
Conditionals
| Form | Meaning |
|---|---|
(if test then else) | exactly three parts; then if the test is not #f, otherwise else |
(cond [test body …+] … [else body …+]) | the first clause whose test is not #f; an else clause must be last. [test] alone returns the test's value. [test => proc] applies proc to the test's value. With no clause taken, the result is void |
(case val [(datum …) body …+] … [else body …+]) | chooses by equal? on the quoted datums, in O(log N) time for N datums; numbers, symbols, characters and strings all work. No match and no else gives void |
(and e …), (or e …) | short-circuit; and returns the last value or #f, or returns the first non-#f value; (and) is #t and (or) is #f |
(when test body …+), (unless test body …+) | run the body only when the test is true (when) or false (unless); otherwise return void |
(match …) | pattern-based dispatch; see Pattern matching |
The last body of if, cond, case, and, or, when and unless is in tail position, so a call there reuses the stack frame. Racket guarantees that tail calls do not grow the stack, which is why loops are written as recursion.
Sequencing
(begin e …+) evaluates in order and returns the last value; at the top of a module or in an internal-definition context, a begin can hold definitions that splice into the enclosing body. (begin0 e0 e …) returns the value of the first expression after running the rest. (begin-for-syntax …) holds compile-time code. (with-continuation-mark key value body) attaches a value to the current continuation frame. Procedure bodies and the clauses above all behave as an implicit begin.
Quote, quasiquote and syntax quote
'(a b c) ; a list of symbols
'(1 . 2) ; a pair
`(1 ,(+ 1 1) ,@(list 3 4)) ; => '(1 2 3 4)
`#(1 ,(+ 1 1)) ; quasiquote also works inside a vector
`(a `(b ,(c ,(+ 1 2)))) ; nested levels: only the innermost , is evaluated
(quote-syntax x) ; a syntax object for x
#'(f x) ; the same shorthand: a syntax template
Inside quasiquote a comma evaluates one expression and a comma-at splices the list it returns. Each nested quasiquote raises the level by one, and each unquote lowers it; an expression is evaluated only at level zero. quasisyntax with #, and #,@ does the same for syntax objects, as in macros.
Modules, requires and the top level
A module body holds require, provide, definitions and expressions; an expression's value is printed when the module is run (except void), which is how racket file.rkt shows (+ 1 2) at the start of a line as 3. See Modules. At the REPL the top level behaves like one big module that accepts new definitions and redefinitions.
Not described
Known, not yet covered
- Reference: the exact order of the expander's steps, the module-level versus top-level distinction for
define, phases and the sets of scopes behind hygiene are not described; Macros says a little about them. - Reference:
#%stratified-body,#%foreign-inline,begin-encourage-inline(a performance hint),lazy-require,define-provide-syntaxanddefine-require-syntaxare named in the Reference's syntax chapter and were not described.
See also
- Control and loops – iteration, exceptions and continuations
- Functions –
lambda, optional and keyword arguments - Scheme: expressions and special forms – the Scheme forms that Racket renames or extends