## 5.4 Non-standard macros and special forms

### 5.4.1 Binding forms for optional arguments

[syntax] (:optional ARGS DEFAULT)
  Use this form for procedures that take a single optional argument. If `ARGS` is the empty list `DEFAULT` is evaluated and returned, otherwise the first element of the list `ARGS`. It is an error if `ARGS` contains more than one value.

      (define (incr x . i) (+ x (:optional i 1)))
      (incr 10)                                   ==> 11
      (incr 12 5)                                 ==> 17

[syntax] (case-lambda (LAMBDA-LIST1 EXP1 ...) ...)
  SRFI-16. Expands into a lambda that invokes the body following the first matching lambda-list.

      (define plus
        (case-lambda
          (() 0)
          ((x) x)
          ((x y) (+ x y))
          ((x y z) (+ (+ x y) z))
          (args (apply + args))))

      (plus)                      ==> 9
      (plus 1)                    ==> 1
      (plus 1 2 3)                ==> 6

  For more information see the documentation for SRFI-16 6

[syntax] (let-optionals ARGS ((VAR1 DEFAULT1) ...) BODY ...)
[syntax] (let-optionals* ARGS ((VAR1 DEFAULT1) ... [RESTVAR]) BODY ...)
  Binding constructs for optional procedure arguments. `ARGS` should be a rest-parameter taken from a lambda-list. `let-optionals` binds `VAR1 ...` to available arguments in parallel, or to `DEFAULT1 ...` if not enough arguments were provided. `let-optionals*` binds `VAR1 ...` sequentially, so every variable sees the previous ones. If a single variable `RESTVAR` is given, then it is bound to any remaining arguments, otherwise it is an error if any excess arguments are provided.

      (let-optionals '(one two) ((a 1) (b 2) (c 3))
        (list a b c) )                               ==> (one two 3)
      (let-optionals* '(one two) ((a 1) (b 2) (c a))
        (list a b c) )                               ==> (one two one)

### 5.4.2 Other binding forms

[syntax] (and-let* (BINDING ...) EXP1 EXP2 ...)
  SRFI-2. Bind sequentially and execute body. `BINDING` can be a list of a variable and an expression, a list with a single expression, or a single variable. If the value of an expression bound to a variable is `#f`, the `and-let*` form evaluates to `#f` (and the subsequent bindings and the body are not executed). Otherwise the next binding is performed. If all bindings/expressions evaluate to a true result, the body is executed normally and the result of the last expression is the result of the `and-let*` form. See also the documentation for SRFI-2 7.

[syntax] (cut SLOT ...)
[syntax] (cute SLOT ...)
  Syntactic sugar for specializing parameters. 8

[syntax] (define-values (NAME ...) EXP)
  Defines several variables at once, with the result values of expression `EXP`. This form may also be used in internal definitions unless the highlevel (syntax-case) macro system is used.

[syntax] (fluid-let ((VAR1 X1) ...) BODY ...)
  Binds the variables `VAR1 ...` dynamically to the values `X1 ...` during execution of `BODY ...`.

[syntax] (let-values (((NAME ...) EXP) ...) BODY ...)
  Binds multiple variables to the result values of `EXP ...`. All variables are bound simultaneously.

[syntax] (let*-values (((NAME ...) EXP) ...) BODY ...)
  Binds multiple variables to the result values of `EXP ...`. The variables are bound sequentially.

      (let*-values (((a b) (values 2 3))
                    ((p) (+ a b)) )
        p)                               ==> 5

[syntax] (letrec-values (((NAME ...) EXP) ...) BODY ...)
  Binds the result values of `EXP ...` to multiple variables at once. All variables are mutually recursive.

      (letrec-values (((odd even)
                         (values
                           (lambda (n) (if (zero? n) #f (even (sub1 n))))
                           (lambda (n) (if (zero? n) #t (odd (sub1 n)))) ) ) )
        (odd 17) )                                                             ==> #t

[syntax] (parameterize ((PARAMETER1 X1) ...) BODY ...)
  Binds the parameters `PARAMETER1 ...` dynamically to the values `X1 ...` during execution of `BODY ...`. (see also: `make-parameter`). Note that `PARAMETER` may be any expression that evaluates to a parameter procedure.

[syntax] (receive (NAME1 ... [. NAMEn]) VALUEEXP BODY ...)
[syntax] (receive VALUEEXP)
  SRFI-8. Syntactic sugar for `call-with-values`. Binds variables to the result values of `VALUEEXP` and evaluates `BODY ...`.

  The syntax

      (receive VALUEEXP)

  is equivalent to

      (receive _ VALUEEXP _)

[syntax] (set!-values (NAME ...) EXP)
  Assigns the result values of expression `EXP` to multiple variables.

### 5.4.3 Substitution forms and macros

[syntax] (define-constant NAME CONST)
  Define a variable with a constant value, evaluated at compile-time. Any reference to such a constant should appear textually after its definition. This construct is equivalent to `define` when evaluated or interpreted. Constant definitions should only appear at toplevel. Note that constants are local to the current compilation unit and are not available outside of the source file in which they are defined. Names of constants still exist in the Scheme namespace and can be lexically shadowed. If the value is mutable, then the compiler is careful to preserve its identity. `CONST` may be any constant expression, and may also refer to constants defined via `define-constant` previously. This for should only be used at top-level.

[syntax] (define-inline (NAME VAR ... [. VAR]) BODY ...)
[syntax] (define-inline NAME EXP)
  Defines an inline procedure. Any occurrence of `NAME` will be replaced by `EXP` or `(lambda (VAR ... [. VAR]) BODY ...)`. This is similar to a macro, but variable-names and -scope will be correctly handled. Inline substitutions take place after macro-expansion. `EXP` should be a lambda-expression. Any reference to `NAME` should appear textually after its definition. Note that inline procedures are local to the current compilation unit and are not available outside of the source file in which they are defined. Names of inline procedures still exist in the Scheme namespace and can be lexically shadowed. This construct is equivalent to `define` when evaluated or interpreted. Inline definitions should only appear at toplevel.

[syntax] (define-macro (NAME VAR ... [. VAR]) EXP1 ...)
[syntax] (define-macro NAME (lambda (VAR ... [. VAR]) EXP1 ...))
  Define a globally visible macro special form. The macro is available as soon as it is defined, i.e. it is registered at compile-time. If the file containing this definition invokes `eval`, then the macro is visible in evaluated expressions during runtime. The second possible syntax for `define-macro` is allowed for portability purposes only. In this case the second argument must be a lambda-expression. Only global macros can be defined using this form.

  This form is also available with the `syntax-case` macro system.

[syntax] (let-macro (MACRODEF ...) EXP1 ...)
  Defines locally scoped macros. `MACRODEF` may be of the form `(NAME (lambda LAMBDALIST BODY ...))` or of the form `((NAME . LAMBDALIST) BODY ...)`. The defined macros are only valid inside the body `EXP1 ...`.

### 5.4.4 Conditional forms

[syntax] (switch EXP (KEY EXP1 ...) ... [(else EXPn ...)])
  This is similar to `case`, but a) only a single key is allowed, and b) the key is evaluated.

[syntax] (unless TEST EXP1 EXP2 ...)
  Equivalent to:

      (if (not TEST) (begin EXP1 EXP2 ...))

[syntax] (when TEST EXP1 EXP2 ...)
  Equivalent to:

      (if TEST (begin EXP1 EXP2 ...))

### 5.4.5 Record structures

[syntax] (define-record NAME SLOTNAME ...)
  Defines a record type. Call `make-NAME` to create an instance of the structure (with one initialization-argument for each slot). `(NAME? STRUCT)` tests any object for being an instance of this structure. Slots are accessed via `(NAME-SLOTNAME STRUCT)` and updated using `(NAME-SLOTNAME-set!` `STRUCT` `VALUE)`.

      (define-record point x y)
      (define p1 (make-point 123 456))
      (point? p1)                      ==> #t
      (point-x p1)                     ==> 123
      (point-y-set! p1 99)
      (point-y p1)                     ==> 99

[syntax] (define-record-printer (NAME RECORDVAR PORTVAR) BODY ...)
[syntax] (define-record-printer NAME PROCEDURE)
  Defines a printing method for record of the type `NAME` by associating a procedure with the record type. When a record of this type is written using `display, write` or `print`, then the procedure is called with two arguments: the record to be printed and an output-port.

      (define-record foo x y z)
      (define f (make-foo 1 2 3))
      (define-record-printer (foo x out)
        (fprintf out "#,(foo ~S ~S ~S)" (foo-x x) (foo-y x) (foo-z x)) )
      (define-reader-ctor 'foo make-foo)
      (define s (with-output-to-string (lambda () (write f))))
      s                                            ==> "#,(foo 1 2 3)"
      (equal? f (with-input-from-string s read)))  ==> #t

  `define-record-printer` works also with SRFI-9 record types.

[syntax] (define-record-type NAME (CONSTRUCTOR TAG ...) PREDICATE (FIELD ACCESSOR [MODIFIER]) ...)
  SRFI-9 record types. For more information see the documentation for SRFI-9 9

### 5.4.6 Other forms

[syntax] (assert EXP [STRING ARG ...])
  Signal error if `EXP` evaluates to false. An optional message `STRING` and arguments `ARG ...` may be supplied to give a more informative error-message. If compiled in unsafe mode (either by specifying the `-unsafe` compiler option or by declaring `(unsafe)`), then this expression expands to an unspecified value.

[syntax] (cond-expand FEATURE-CLAUSE ...)
  SRFI-0. Expands by selecting feature clauses. Predefined feature-identifiers are `srfi-0`, `srfi-2`, `srfi-6`, `srfi-8`, `srfi-9`, `srfi-10`, and `chicken`. In `strict-srfi-0` mode only `srfi-0` and `chicken` are defined. If the source file containing this form is currently compiled, the feature `compiling` is defined. For further information, see the documentation for SRFI-0 10 This form is allowed to appear in non-toplevel expressions.

[syntax] (critical-section BODY ...)
  Evaluate `BODY ...` with timer-interrupts temporarily disabled.

[syntax] (ensure PREDICATE EXP [ARGUMENTS ...])
  Evaluates the expression `EXP` and applies the one-argument procedure `PREDICATE` to the result. If the predicate returns `#f` an error is signaled, otherwise the result of `EXP` is returned. If compiled in unsafe mode (either by specifying the `-unsafe` compiler option or by declaring `(unsafe)`), then this expression expands to an unspecified value. If specified, the optional `ARGUMENTS` are used as arguments to the invocation of the error-signalling code, as in `(error ARGUMENTS ...)`. If no `ARGUMENTS` are given, a generic error message is displayed with the offending value and `PREDICATE` expression.

[syntax] (eval-when (SITUATION ...) EXP ...)
  Controls evaluation/compilation of subforms. `SITUATION` should be one of the symbols `eval`, `compile` or `load`. When encountered in the evaluator, and the situation specifier `eval` is not given, then this form is not evaluated and an unspecified value is returned. When encountered while compiling code, and the situation specifier `compile` is given, then this form is evaluated at compile-time. When encountered while compiling code, and the situation specifier `load` is not given, then this form is ignored and an expression resulting into an unspecified value is compiled instead.

  Note: It is currently not possible to use `define-syntax` or `define` inside `eval-when` forms when hygienic macros are enabled.

[syntax] (include STRING)
  Include toplevel-expressions from a given source file in the currently compiled/interpreted program. If the included file has the extension `.scm`, then it may be omitted. The file is searched in the current directory and, if not found, in all directories specified in the `-include-path` option. The expressions are treated as toplevel expressions, so it's generally a good idea to use `include` only in a toplevel context.

[syntax] (nth-value N EXP)
  Returns the `N`th value (counting from zero) of the values returned by expression `EXP`.

[syntax] (time EXP1 ...)
  Evaluates `EXP1 ...` and print elapsed time and memory information. The result of the last expression is returned.

6 http://srfi.schemers.org/srfi-16/srfi-16.html

7 http://srfi.schemers.org/srfi-2/srfi-2.html

8 http://srfi.schemers.org/srfi-26/srfi-26.html

9 http://srfi.schemers.org/srfi-9/srfi-9.html

10 http://srfi.schemers.org/srfi-0/srfi-0.html