chickadee » chicken » special-forms

Outdated CHICKEN release

This is a manual page for an old and unsupported version of CHICKEN. If you are still using it, please consider migrating to the latest version. You can find the manual for the latest release here.

Non-standard macros and special forms

Making extra libraries and extensions available

require-extension

(require-extension ID ...)syntax

This is equivalent to (require-library ID ...) but performs an implicit import, if necessary. Since version 4.4.0, ID may also be an import specification (using rename, only, except or prefix).

To make long matters short - just use require-extension and it will normally figure everything out for dynamically loadable extensions and core library units.

This implementation of require-extension is compliant with SRFI-55 (see the SRFI-55 document for more information).

require-library

(require-library ID ...)syntax

This form does all the necessary steps to make the libraries or extensions given in ID ... available. It loads syntactic extensions, if needed and generates code for loading/linking with core library modules or separately installed extensions.

During interpretation/evaluation require-library performs one of the following:

  • If ID names a built-in feature chicken srfi-0 srfi-2 srfi-6 srfi-8 srfi-9 srfi-10 srfi-17 srfi-23 srfi-30 srfi-39 srfi-55, then nothing is done.
  • If ID names one of the syntactic extensions chicken-syntax chicken-ffi-syntax, then this extension will be loaded.
  • If ID names one of the core library units shipped with CHICKEN, then a (load-library 'ID) will be performed.
  • If ID names an installed extension with the syntax or require-at-runtime attribute, then the extensions is loaded at compile-time, probably doing a run-time (require ...) for any run-time requirements.
  • Otherwise, (require-library ID) is equivalent to (require 'ID).

During compilation, one of the following happens instead:

  • If ID names a built-in feature chicken srfi-0 srfi-2 srfi-6 srfi-8 srfi-9 srfi-10 srfi-17 srfi-23 srfi-30 srfi-39 srfi-55, then nothing is done.
  • If ID names one of the syntactic extensions chicken-syntax chicken-ffi-syntax, then this extension will be loaded at compile-time, making the syntactic extensions available in compiled code.
  • If ID names one of the core library units shipped with CHICKEN, or if the option -uses ID has been passed to the compiler, then a (declare (uses ID)) is generated.
  • If ID names an installed extension with the syntax or require-at-runtime attribute, then the extension is loaded at compile-time, and code is emitted to (require ...) any needed run-time requirements.
  • Otherwise (require-library ID) is equivalent to (require 'ID).

ID should be a pure extension name and should not contain any path prefixes (for example dir/lib... is illegal).

ID may also be a list that designates an extension-specifier. Currently the following extension specifiers are defined:

  • (srfi NUMBER ...) is required for SRFI-55 compatibility and is fully implemented
  • (version ID NUMBER) is equivalent to ID, but checks at compile-time whether the extension named ID is installed and whether its version is equal or higher than NUMBER. NUMBER may be a string or a number, the comparison is done lexicographically (using string>=?).

use

(use ID ...)syntax

use is just a shorter alias for require-extension.

require-extension-for-syntax

(require-extension-for-syntax ID ...)syntax

An abbreviation for the idiom:

(begin-for-syntax (require-library ID ...))  ; load extension at expansion-time
(import-for-syntax ID ...)                   ; import extension for use in syntax-transformers

use-for-syntax

(use-for-syntax ID ...)syntax

use is just a shorter alias for require-extension-for-syntax (which is quite a mouthful).

Binding forms for optional arguments

optional

(optional ARGS DEFAULT)syntax

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

case-lambda

(case-lambda (LAMBDA-LIST1 EXP1 ...) ...)syntax

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)                      ==> 0
(plus 1)                    ==> 1
(plus 1 2 3)                ==> 6

For more information see the documentation for SRFI-16

let-optionals

(let-optionals ARGS ((VAR1 DEFAULT1) ...) BODY ...)syntax

Binding constructs for optional procedure arguments. ARGS is normally 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. 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*

(let-optionals* ARGS ((VAR1 DEFAULT1) ... [RESTVAR]) BODY ...)syntax

Binding constructs for optional procedure arguments. ARGS is normally 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 a))
  (list a b c) )                               ==> (one two one)

Other binding forms

and-let*

(and-let* (BINDING ...) EXP1 EXP2 ...)syntax

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.

letrec*

(letrec* ((VARIABLE EXPRESSION) ...) BODY ...)syntax

Implements R6RS/R7RS letrec*. letrec* is similar to letrec but binds the variables sequentially and is to letrec what let* is to let.

rec

(rec NAME EXPRESSION)syntax
(rec (NAME VARIABLE ...) BODY ...)syntax

Allows simple definition of recursive definitions. (rec NAME EXPRESSION) is equivalent to (letrec ((NAME EXPRESSION)) NAME) and (rec (NAME VARIABLE ...) BODY ...) is the same as (letrec ((NAME (lambda (VARIABLE ...) BODY ...))) NAME).

cut

(cut SLOT ...)syntax
(cute SLOT ...)syntax

Syntactic sugar for specializing parameters.

define-values

(define-values (NAME ...) VALUEEXP)syntax
(define-values (NAME1 ... NAMEn . NAMEn+1) VALUEEXP)syntax
(define-values NAME VALUEEXP)syntax

Defines several variables at once, with the result values of expression VALUEEXP, similar to set!-values.

fluid-let

(fluid-let ((VAR1 X1) ...) BODY ...)syntax

Binds the variables VAR1 ... dynamically to the values X1 ... during execution of BODY .... This implements SRFI-15.

let-values

(let-values (((NAME ...) VALUEEXP) ...) BODY ...)syntax

Binds multiple variables to the result values of VALUEEXP .... All variables are bound simultaneously. Like define-values, the (NAME ...) expression can be any basic lambda list (dotted tail notation is supported). This implements SRFI-11.

let*-values

(let*-values (((NAME ...) VALUEEXP) ...) BODY ...)syntax

Binds multiple variables to the result values of VALUEEXP .... The variables are bound sequentially. Like let-values, the (NAME ...) expression can be any basic lambda list (dotted tail notation is supported). This is also part of SRFI-11.

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

letrec-values

(letrec-values (((NAME ...) VALUEEXP) ...) BODY ...)syntax

Binds the result values of VALUEEXP ... to multiple variables at once. All variables are mutually recursive. Like let-values, the (NAME ...) expression can be any basic lambda list (dotted tail notation is supported).

(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

parameterize

(parameterize ((PARAMETER1 X1) ...) BODY ...)syntax

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

receive

(receive (NAME ...) VALUEEXP BODY ...)syntax
(receive (NAME1 ... NAMEn . NAMEn+1) VALUEEXP BODY ...)syntax
(receive NAME VALUEEXP BODY ...)syntax
(receive VALUEEXP)syntax

SRFI-8. Syntactic sugar for call-with-values. Binds variables to the result values of VALUEEXP and evaluates BODY ..., similar define-values but lexically scoped.

(receive VALUEEXP) is equivalent to (receive _ VALUEEXP _). This shortened form is not described by SRFI-8.

set!-values

(set!-values (NAME ...) VALUEEXP)syntax
(set!-values (NAME1 ... NAMEn . NAMEn+1) VALUEEXP)syntax
(set!-values NAME VALUEEXP)syntax

Assigns the result values of expression VALUEEXP to multiple variables, similar to define-values.

Substitution forms and macros

define-constant

(define-constant NAME CONST)syntax

Defines 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, but it must be possible to evaluate the expression at compile-time.

define-inline

(define-inline (NAME VAR ...) BODY ...)syntax
(define-inline (NAME VAR ... . VAR) BODY ...)syntax
(define-inline NAME EXP)syntax

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 are handled correctly.

Inline substitutions take place after macro-expansion, and any reference to NAME should appear textually after its definition. 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. Inline definitions should only appear at the toplevel.

Note that the inline-limit compiler option does not affect inline procedure expansion, and self-referential inline procedures may cause the compiler to enter an infinite loop.

In the third form, EXP must be a lambda expression.

This construct is equivalent to define when evaluated or interpreted.

define-for-syntax

(define-for-syntax (NAME VAR ...) EXP1 ...)syntax
(define-for-syntax (NAME VAR1 ... VARn . VARn+1) EXP1 ...)syntax
(define-for-syntax NAME [VALUE])syntax

Defines the toplevel variable NAME at macro-expansion time. This can be helpful when you want to define support procedures for use in macro-transformers, for example.

Note that define-for-syntax definitions within a module are implicitly added to that module's import library. Refer to the documentation on import libraries for more information.

define-compiler-syntax

(define-compiler-syntax NAME)syntax
(define-compiler-syntax NAME TRANSFORMER)syntax

Defines what is usually called a compiler macro in Lisp: NAME should be the name of a globally or locally bound procedure. Any direct call to this procedure will be transformed before compilation, which allows arbitrary rewritings of function calls.

TRANSFORMER can be a syntax-rules expression or a transformer procedure (as returned by er-macro-transformer or ir-macro-transformer). Returning the original form in an explicit/implicit-renaming macro or simply "falling trough" all patterns in a syntax-rules form will keep the original expression and compile it normally.

In the interpreter this form does nothing and returns an unspecified value.

Compiler-syntax is always local to the current compilation unit and can not be exported. Compiler-syntax defined inside a module is not visible outside of that module.

define-compiler-syntax should only be used at top-level. Local compiler-syntax can be defined with let-compiler-syntax.

(define-compiler-syntax +
  (syntax-rules ()
    ((_) 1)
    ((_ x 0) x) ) )

If no transformer is given, then (define-compiler-syntax NAME) removes any compiler-syntax definitions for NAME.

let-compiler-syntax

(let-compiler-syntax ((NAME [TRANSFORMER]) ...) BODY ...)syntax

Allows definition local compiler macros, which are only applicable inside BODY .... By not providing a TRANSFORMER expression, compiler-syntax for specific identifiers can be temporarily disabled.

Conditional forms

select

(select EXP ((KEY ...) EXP1 ...) ... [(else EXPn ...)])syntax

This is similar to case, but the keys are evaluated.

unless

(unless TEST EXP1 EXP2 ...)syntax

Equivalent to:

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

when

(when TEST EXP1 EXP2 ...)syntax

Equivalent to:

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

Record structures

define-record

(define-record NAME SLOTNAME ...)syntax

Defines a record type. This defines a number of procedures for creating, accessing, and modifying record members.

Call make-NAME to create an instance of the structure (with one initialization-argument for each slot, in the listed order).

(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
SRFI-17 setters

SLOTNAME may alternatively also be of the form

 (setter SLOTNAME)

In this case the slot can be read with (NAME-SLOTNAME STRUCT) as usual, and modified with (set! (NAME-SLOTNAME STRUCT) VALUE) (the slot-accessor has an associated SRFI-17 "setter" procedure) instead of the usual (NAME-SLOTNAME-set! STRUCT VALUE).

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

define-record-type

(define-record-type NAME (CONSTRUCTOR TAG ...) PREDICATE (FIELD ACCESSOR [MODIFIER]) ...)syntax

SRFI-9 record types. For more information see the documentation for SRFI-9.

As an extension the MODIFIER may have the form (setter PROCEDURE), which will define a SRFI-17 setter-procedure for the given PROCEDURE that sets the field value. Usually PROCEDURE has the same name is ACCESSOR (but it doesn't have to).

define-record-printer

(define-record-printer (NAME RECORDVAR PORTVAR) BODY ...)syntax
(define-record-printer NAME PROCEDURE)syntax

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-type foo (make-foo x y z) foo?
  (x foo-x)
  (y foo-y)
  (z foo-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

Other forms

assert

(assert EXP [STRING ARG ...])syntax

Signals an 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. The result is the value of EXP.

begin-for-syntax

(begin-for-syntax EXP ...)syntax

Equivalent to (begin EXP ...), but performs the evaluation of the expression during macro-expansion time.

cond-expand

(cond-expand FEATURE-CLAUSE ...)syntax

Expands by selecting feature clauses. This form is allowed to appear in non-toplevel expressions.

Predefined feature-identifiers are "situation" specific:

compile
chicken, compiling, library, eval, extras, utils, regex, srfi-0, srfi-1, srfi-2, srfi-4, srfi-6, srfi-8, srfi-9, srfi-10, srfi-11, srfi-12, srfi-15, srfi-16, srfi-17, srfi-23, srfi-26, srfi-28, srfi-30, srfi-31, srfi-39, srfi-55, srfi-61, srfi-62, srfi-69
load
chicken, extras, srfi-0, srfi-2, srfi-6, srfi-8, srfi-9, srfi-10, srfi-12, srfi-17, srfi-23, srfi-28, srfi-30, srfi-39, srfi-55, srfi-61, srfi-62, srfi-69. library is implicit.
eval
csi, chicken, extras, srfi-0, srfi-2, srfi-6, srfi-8, srfi-9, srfi-10, srfi-11, srfi-12, srfi-15, srfi-16, srfi-17, srfi-23, srfi-26, srfi-28, srfi-30, srfi-31, srfi-39, srfi-55, srfi-61, srfi-62, srfi-69. library is implicit.

The following feature-identifier classes are available in all situations: (machine-byte-order), (machine-type), (software-type), (software-version), where the actual feature-identifier is platform dependent.

In addition the following feature-identifiers may exist: cross-chicken, dload, manyargs, ptables.

For further information, see the documentation for SRFI-0.

delay-force

CHICKEN supports the R7RS delay-force syntax which allows for iterative lazy algorithms to be expressed in bounded space.

For more information regarding this behaviour, see the SRFI-45 rationale.

ensure

(ensure PREDICATE EXP [ARGUMENTS ...])syntax

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.

eval-when

(eval-when (SITUATION ...) EXP ...)syntax

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.

The following table should make this clearer:

In compiled codeIn interpreted code
evalignoreevaluate
compileevaluate at compile timeignore
loadcompile as normalignore

include

(include STRING)syntax

Include toplevel-expressions from the 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.

nth-value

(nth-value N EXP)syntax

Returns the Nth value (counting from zero) of the values returned by expression EXP.

time

(time EXP1 ...)syntax

Performs a major garbage collection, evaluates EXP1 ... and prints elapsed CPU time and some values about GC use, like time spent in major GCs, number of minor and major GCs. The output is sent to the port that is the current value of (current-error-port). Nested invocations of this form will give incorrect results for all output but the innermost.


Previous: Non-standard read syntax

Next: Macros

Contents »