Prelude Macros
These are the main macros defined by the prelude.
Definition Forms
define
(define (id . args) body ...)
=> (define-values (id)
(lambda% args body ...))
(define id expr)
=> (define-values (id) expr)
def
(def (id . args) body ...)
=> (define-values (id)
(lambda args body ...))
(def ((head . rest) . args) body ...)
=> (def (head . rest)
(lambda args body ...))
(def id expr)
=> (define-values (id) expr)
Compared with define
, which defines lambdas with the core Scheme lambda%
form,
def
uses the extended lambda
form, and supports curried definitions.
def*
(def* id
(args body ....) ...)
=>
(def id
(case-lambda (args body ...) ...))
Examples:
> (def* foo
(() ['no-arg])
((x) ['one-arg x])
(rest ['more-than-one rest]))
> (foo 1)
(one-arg 1)
> (foo 1 2)
(more-than-one (1 2))
defvalues
(defvalues (id ...) expr)
=> (define-values (id ...) expr)
defsyntax
(defsyntax (id . args) body ...)
=> (define-syntax id (lambda args body ...))
(defsyntax id expr)
=> (define-syntax id expr)
defrules
(defrules id (keyword-id ...)
(pat [fender] body) ...)
=> (defsyntax id
(syntax-rules (keyword-id ...)
(pat [fender] body) ...))
defalias
(defalias id alias-id)
=> (define-alias id alias-id)
Binding Forms
let*-values
(let*-values (((id ...) expr) rest ...) body ...)
=> (let-values (((id) expr))
(let*-values rest body ...))
(let*-values () body ...)
=> (let-values () body ...)
let
(let id ((var expr) ...) body ...)
=> ((letrec (id (lambda% (var ...) body ...))) expr ...)
(let bind body ...)
=> (let-values (bind-values) body ...)
(let (bind ...) body ...)
=> (let-values (bind-values ...) body ...)
<bind>:
((values id ...) expr)
(id expr)
<bind-values>:
(((id ...) expr))
let*
(let* (bind rest ...) body ...)
=> (let bind (let* (rest ...) body ...))
(let* () body ...)
=> (let () body ...)
letrec letrec*
(letrec[*] bind body ...)
=> (letrec[*]-values (bind-values) body ...)
(letrec[*] (bind ...) body ...)
=> (letrec[*]-values (bind-values ...) body ...)
lambda
(lambda (arg ...) body ...)
(lambda (arg ... . id) body)
<arg>:
id ; required argument
(id default) ; optional argument
key: (id default) ; keyword argument
The extended lambda form that supports optional and keyword arguments.
set!
(set! id expr)
(set! setq-macro-id expr)
=> apply setq-macro expander
(set! (setf-macro-id . args) . rest)
=> apply setf-macro expander
(set! (getf-id arg ...) expr)
=> (getf-id-set! arg ... expr)
And when you got bindings, you want your mutator too. As they say, mostly functional.
Common Syntactic Sugar
and or
(and expr ...)
(or expr ...)
case cond
(cond cond-clause ...)
(case case-clause ...)
The well known conditional macros; case
has its extended form supporting =>
dispatch.
when unless
(when test expr ...)
=> (if test (begin expr ...) #!void)
(unless test expr ...)
=> (if test #!void (begin expr ...))
do do-while
(do ((var init step ...) ...)
(test fini ...)
body ...)
(do-while hd (test fini ...) body ...)
=> (do hd ((not test) fini ...) body ...)
The common iteration macro and its inverted form.
begin0
(begin0 expr rest ...)
=> (let (val expr) rest ... val)
rec
(rec id expr)
=> (letrec ((id expr)) id)
(rec (values id ...) expr)
=> (letrec ((values id ...) expr) (values id ...))
(rec (id . args) body ...)
=> (letrec (id (lambda args body ...)) id)
Short recursive definition form.
alet alet* and-let*
(alet bind body ...)
(alet (bind ...) body ...)
(alet* bind body ...)
(alet* (bind ...) body ...)
(defalias and-let* alet*)
Anaphoric lets which short circuit to #f
if any of the bindings is #f
.
Examples:
> (alet ((a [1 2])
(b #f))
[a b])
#f
> (alet ((a [1 2])
(b #t))
[a b])
((1 2) #t)
@list
(@list)
=> '()
(@list :: tl)
=> tl
(@list xs ellipsis)
=> xs
(@list xs ellipsis . rest)
=> (foldr cons (@list . rest) xs)
(@list x . xs)
=> (cons x (@list . xs)))
(@list . tl)
=> tl
This is the reader macro for [...]
.
quasiquote
(quasiquote expr)
delay
(delay expr)
The promise to eval expr
.
cut
(cut arg ...)
if you don't know how this works, stop and read the SRFI. Most useful little macro ever.
Examples:
> (filter (cut < <> 10) [1 10 2 20])
(1 2)
> (def fn (cut list 'a 'b))
> (fn)
(a b)
parameterize
(parameterize ((paremter-id expr) ...) body ...)
Examples:
> (def foo (make-parameter #f))
> (foo)
#f
> (parameterize ((foo 100))
(foo))
100
let/cc let/esc
(let/cc id body ...)
=> (call/cc (lambda (id) body ...))
(let/esc id body ...)
=> (call/esc (lambda (id) body ...))
call/esc
is really the same thing as call/cc
in Gerbil on Gambit.
unwind-protect
(unwind-protect body postlude)
@bytes
(@bytes "...")
=> (quote #u8(...))
Converts a utf8 encoded string to a u8vector at expansion time.
syntax-error
(syntax-error message detail ...)
Raises a syntax error; used for meaningful error reporting in syntax-rules macros.
Runtime Aliases
car-set! cdr-set!
(defalias car-set! set-car!)
(defalias cdr-set! set-cdr!)
string-ref-set!
(defalias string-ref-set! string-set!)
*vector-ref-set!
(defalias vector-ref-set! vector-set!)
(defalias s8vector-ref-set! s8vector-set!)
(defalias u8vector-ref-set! u8vector-set!)
(defalias s16vector-ref-set! s16vector-set!)
(defalias u16vector-ref-set! u16vector-set!)
(defalias s32vector-ref-set! s32vector-set!)
(defalias u32vector-ref-set! u32vector-set!)
(defalias s64vector-ref-set! s64vector-set!)
(defalias u64vector-ref-set! u64vector-set!)
(defalias f32vector-ref-set! f32vector-set!)
(defalias f64vector-ref-set! f64vector-set!)
These binding enable you to use set!
with *vector-ref
.
Examples
> (def foo (vector 1 2 3))
> (set! (vector-ref foo 1) 4)
> foo
#(1 4 3)
call/values call/parameters
(defalias call/values call-with-values)
(defalias call/parameters call-with-parameters)
randeom-bytes random-source-make-bytes
(defalias random-bytes random-u8vector)
(defalias random-source-make-bytes random-source-make-u8vectors))
MOP Macros
defclass-type defstruct-type
(defclass-type id super make instance? type-body ...)
(defstruct-type id super make instance? type-body ...)
<type-body>:
name: id ; type name
id: id ; type id
constructor: method-id ; constructor method id
properties: expr ; additional type properties
slots: ((id getf setf) ...) ; class slots
mixin: ((id getf setf) ...) ; mixin class slots
struct: <boolean> ; #t for structs
final: <boolean> ; final class?
metaclass: id ; metaclass type
Low level class type definition facilities.
defclass defstruct define-class define-struct
(defclass id (slot ...) typedef-option ...)
(defclass (id super ...) (slot ...) typedef-option ...)
(defstruct id (slot ...) typedef-option ...)
(defstruct (id super ...) (slot ...) typedef-option ...)
(defalias define-class defclass)
(defalias define-struct defstruct)
<typedef-option>:
name: id ; type name
id: id ; type id
constructor: id ; constructor method id
final: <boolean> ; #t for final types
struct: <boolean> ; #t for structs
transparent: <boolean> ; #t for equality checks and printability
equal: <boolean> or <list> ; a list of slots to consider for equal? checks, #t for all fields
print: <boolean> or <list> ; a list of slots to print, #t for all fields
metaclass: id ; metaclass type
Canonical class type definition macro.
defmethod
(defmethod {method-id type}
expr
[rebind: <boolean>])
Defines a method method-id
for type type
, which must be
a class type.
The :std/generic
library extends the form for generic methods.
@method
{obj.id arg ...}
{id obj arg ...}
(@method id obj arg ...)
=> (call-method obj 'id arg ...)
This is the reader macro for {...}
, the method invocation operator.
@ (slot reference)
(@ obj id)
=> (slot-ref obj 'id)
(@ obj id rest ...)
=> (@ (@ obj id) rest ...)
Dynamic slot reference macro.
@-set!
(set! (@ obj id ...) val)
=> (@-set! obj id ... val)
(@-set! obj id val)
=> (slot-set! obj 'id val)
(@-set! obj id rest ... last val)
=> (@-set! (@ obj id rest ...) last val)
Dynamic slot mutation macro.
System Classes
:t
(defsystem-class-info :t t::t () true)
:object
(defsystem-class-info :object object::t (t::t) true)
:immediate
(defsystem-class-info :immediate immediate::t (t::t) immediate?)
:boolean
(defsystem-class-info char::t (immediate::t) char?)
:boolean
(defsystem-class-info :boolean boolean::t (immediate::t) boolean?)
:atom
(defsystem-class-info :atom atom::t (immediate::t) atom?)
:void
(defsystem-class-info :void void::t (atom::t) void?)
:eof
(defsystem-class-info :eof eof::t (atom::t) eof-object?)
:true
(defsystem-class-info :true true::t (boolean::t atom::t) true?)
:false
(defsystem-class-info :false false::t (boolean::t atom::t) not)
:special
(defsystem-class-info :special special::t (atom::t) special?)
:number
(defsystem-class-info :number number::t (t::t) number?)
:real
(defsystem-class-info :real real::t (number::t) real?)
:integer
(defsystem-class-info :integer integer::t (real::t) integer?)
:fixnum
(defsystem-class-info :fixnum fixnum::t (integer::t immediate::t) fixnum?)
:bignum
(defsystem-class-info :bignum bignum::t (integer::t) ##bignum?)
:ratnum
(defsystem-class-info :ratnum ratnum::t (real::t) ##ratnum?)
:flonum
(defsystem-class-info :flonum flonum::t (real::t) flonum?)
:cpxnum
(defsystem-class-info :cpxnum cpxnum::t (number::t) ##cpxnum?)
:symbolic
(defsystem-class-info :symbolic symbolic::t (t::t) symbolic?)
:symbol
(defsystem-class-info :symbol symbol::t (symbolic::t) symbol?)
:keyword
(defsystem-class-info :keyword keyword::t (symbolic::t) keyword?)
:list
(defsystem-class-info :list list::t (t::t) list?)
:pair
(defsystem-class-info :pair pair::t (list::t) pair?)
:null
(defsystem-class-info :null null::t (list::t atom::t) null?)
:sequence
(defsystem-class-info :sequence sequence::t (t::t) sequence?)
:vector
(defsystem-class-info :vector vector::t (sequence::t) vector?)
:string
(defsystem-class-info :string string::t (sequence::t) string?)
:hvector
(defsystem-class-info :hvector hvector::t (sequence::t) hvector?)
:u8vector
(defsystem-class-info :u8vector u8vector::t (hvector::t) u8vector?)
:s8vector
(defsystem-class-info :s8vector s8vector::t (hvector::t) s8vector?)
:u16vector
(defsystem-class-info :u16vector u16vector::t (hvector::t) u16vector?)
:s16vector
(defsystem-class-info :s16vector s16vector::t (hvector::t) s16vector?)
:u32vector
(defsystem-class-info :u32vector u32vector::t (hvector::t) u32vector?)
:s32vector
(defsystem-class-info :s32vector s32vector::t (hvector::t) s32vector?)
:u64vector
(defsystem-class-info :u64vector u64vector::t (hvector::t) u64vector?)
:s64vector
(defsystem-class-info :s64vector s64vector::t (hvector::t) s64vector?)
:f32vector
(defsystem-class-info :f32vector f32vector::t (hvector::t) f32vector?)
:f64vector
(defsystem-class-info :f64vector f64vector::t (hvector::t) f64vector?)
:values
(defsystem-class-info :values values::t (t::t) ##values?)
:box
(defsystem-class-info :box box::t (t::t) box?)
:frame
(defsystem-class-info :frame frame::t (t::t) ##frame?)
:continuation
(defsystem-class-info :continuation continuation::t (t::t) continuation?)
:promise
(defsystem-class-info :promise promise::t (t::t) promise?)
:weak
(defsystem-class-info :weak weak::t (t::t) weak?)
:foreign
(defsystem-class-info :foreign foreign::t (t::t) foreign?)
:procedure
(defsystem-class-info :procedure procedure::t (t::t) procedure?)
:time
(defsystem-class-info :time time::t (t::t) time?)
:thread
(defsystem-class-info :thread thread::t (t::t) thread?)
:thread-group
(defsystem-class-info :thread-group thread-group::t (t::t) thread-group?)
:mutex
(defsystem-class-info :mutex mutex::t (t::t) mutex?)
:condvar
(defsystem-class-info :condvar condvar::t (t::t) condvar?)
:port
(defsystem-class-info :port port::t (t::t) port?)
:object-port
(defsystem-class-info :object-port object-port::t (port::t) object-port?)
:character-port
(defsystem-class-info :character-port character-port::t (object-port::t) character-port?)
:byte-port
(defsystem-class-info :byte-port byte-port::t (character-port::t) byte-port?)
:device-port
(defsystem-class-info :device-port device-port::t (byte-port::t) device-port?)
:vector-port
(defsystem-class-info :vector-port vector-port::t (object-port::t) vector-port?)
:string-port
(defsystem-class-info :string-port string-port::t (character-port::t) string-port?)
:u8vector-port
(defsystem-class-info :u8vector-port u8vector-port::t (byte-port::t) u8vector-port?)
:raw-device-port
(defsystem-class-info :raw-device-port raw-device-port::t (port::t) raw-device-port?)
:tcp-server-port
(defsystem-class-info :tcp-server-port tcp-server-port::t (object-port::t) tcp-server-port?)
:udp-port
(defsystem-class-info :udp-port udp-port::t (object-port::t) udp-port?)
:directory-port
(defsystem-class-info :directory-port directory-port::t (object-port::t) directory-port?)
:event-queue-port
(defsystem-class-info :event-queue-port event-queue-port::t (object-port::t) event-queue-port?)
:table
(defsystem-class-info :table table::t (t::t) table?)
:readenv
(defsystem-class-info :readenv readenv::t (t::t) readenv?)
:writeenv
(defsystem-class-info :writeenv writeenv::t (t::t) writeenv?)
:readtable
(defsystem-class-info :readtable readtable::t (t::t) readtable?)
:processor
(defsystem-class-info :processor processor::t (t::t) processor?)
:vm
(defsystem-class-info :vm vm::t (t::t) vm?)
:file-info
(defsystem-class-info :file-info file-info::t (t::t) file-info?)
:socket-info
(defsystem-class-info :socket-info socket-info::t (t::t) socket-info?)
:address-info
(defsystem-class-info :address-info address-info::t (t::t) address-info?)
Pattern Matching
match
(match expr
(pattern body ...) ...
[(else body ...)])
<pattern>:
(? test) ; predicate test with the `?` predicate constructor
(? test pattern) ; test and match a pattern
(? test => pattern) ; test and match a pattern on the value of the test
(? test :: proc => pattern) ; test and match with a filter
(and pattern ...) ; match all patterns
(or pattern ...) ; match any pattern
(not pattern) ; negated match
(cons pattern1 pattern2) ; destructure a pair like cons
(cons* pattern ... pattern-tail) ; destructure a list like cons*
[pattern ...] ;
(@list pattern ...) ; destructure a list like @list
(box pattern) ;
#&pattern ; destructure a box
(values pattern ...) ; destructure a values tuple
(vector pattern ...) ;
#(pattern ...) ; destructure a vector
(struct-id pattern ...) ; destructure a struct
(class-id (slot pattern) ...) ; destructure a class
(eq? val) ; match eq? to val
(eqv? val) ; match eqv? to val
(equal? val) ; match equal? to val
(quote expr) ; match eq?/eqv?/equal? to a quoted value
(quasiquote datum) ; destructure with quasiquote
(apply getf pattern) ; applicative destructuring
(match-macro arg ...) ; apply match macro expander
_ ; match any and ignore
id ; match any and bind to id
datum ; match eq?/eqv?/equal? to a datum
(match <> (match-pattern body ...) ...)
=> (lambda (obj) (match obj (match-pattern body ...) ...))
(match <...> (match-pattern body ...) ...)
=> (lambda args (match args (match-pattern body ...) ...))
The fundamental destructuring pattern match macro; you've seen many and this one is very much like them.
Examples:
> (def lst [1 2 3])
> (match lst
([0 1 c] "starts with 0 1")
([a _ c] (list c a))
(_ #f))
(3 1)
> (let loop ((rest [1 2]))
(match rest
([v . rest] (displayln v) (loop rest))
([] (displayln 'end))))
1
2
end
> (def foo (match <>
((? (and number? inexact?)) 'inexact)
((? number?) 'number)
((and (? string?) (not "")) 'string)
(_ 'other)))
> (foo 10)
number
> (foo 2.0)
inexact
> (foo "")
other
> (foo "bar")
string
match*
(match* (expr ...)
((pattern ...) body) ...)
Matches multiple objects in sequence.
Examples:
> (match* (#t [1 2])
((#f [a 0]) 'a)
((#t [a]) 'b)
((#t [_ b]) 'c)
(else 'd))
c
with with*
(with (pattern expr) body ...)
=> (match expr (pattern body ...))
(with ((pattern expr) ...) body ...)
=> (match* (expr ...) ((pattern ...) body ...))
(with () body ...)
=> (let () body ...)
(with* (hd rest ...) body ...)
=> (with hd (with* (rest ...) body ...))
(with* () body ...)
=> (let () body ...)
Short-form destructuring bind macros.
Examples:
> (with ([a b . c] (iota 4))
(list a b c))
(0 1 (2 3))
? (predicate constructor)
(? (and pred ...) obj)
=> (and (? pred obj) ...)
(? (or pred ...) obj)
=> (or (? pred obj) ...)
(? (not pred) obj)
=> (not (? pred obj))
(? pred obj)
=> (pred obj)
(? pred)
=> (lambda (obj) (? pred obj))
(? pred => K)
=> (lambda (obj)
(alet (val (? pred obj))
(K val)))
(? pred :: proc)
=> (lambda (obj)
(and (? pred obj)
(proc obj)))
(? pred :: proc => K)
=> (lambda (obj)
(and (? pred obj)
(K (proc obj))))
The predicate constructor macro.
Examples:
> (? (and number? fixnum?) 1000)
#t
> (? (and number? fixnum?))
#<procedure #1>
defsyntax-for-match
(defsyntax-for-match id match-macro-expr [macro-expr])
Defines a match macro expander with name id
, with optionally a regular expander for the
same identifier.
Macros for Syntax
The following macros are only available for syntax (phi = 1).
syntax-case syntax syntax/loc
(syntax-case stx (keyword-id ...)
(pat [fender] body) ...)
(syntax expr)
(syntax/loc src-stx expr)
The well-known syntax
and syntax-case
macros, first defined in "Extending the Scope
of Syntactic Abstraction" by Waddell and Dybvig and popularized by Racket.
syntax/loc
is like syntax, only it assigns the source location to that of src-stx
syntax-rules
(syntax-rules (keyword-id ...)
(pat [fender] expr) ...)
The familiar syntax-rules
macro from R5RS, extended with pattern fenders like syntax-case
and meaningful underscores.
with-syntax with-syntax*
(with-syntax ((pat expr) ...) body)
(with-syntax* ((bind expr) ...) body)
<bind>:
(values id ...) ; value binding
pat ; syntax binding
The common with-syntax
macro is widely used in Racket.
Its sequence form with-syntax*
is like a sequence of with-syntax
, with the Gerbilic
allowance for value bindings with let*
semantics.
identifier-rules
(identifier-rules (keyword-id)
(pat [fender] expr) ...)
Variant of syntax-rules
that constructs a setq macro and not a plain macro expander.
Module Sugar
require
(require feature ...)
Fails with a syntax error if the cond-expand
features feature ...
are not satisfied.
defsyntax-for-import defsyntax-for-export defsyntax-for-import-export
(defsyntax-for-import id expr)
(defsyntax-for-import (id . args) body ...)
=> (defsyntax-for-import id (lambda args body ...))
(defsyntax-for-export id expr)
(defsyntax-for-export (id . args) body ...)
=> (defsyntax-for-export id (lambda args body ...))
(defsyntax-for-import-export id expr)
(defsyntax-for-import-export (id . args) body ...)
=> (defsyntax-for-import-export id (lambda args body ...))
Define import and export macro expanders.
for-syntax for-template
(import (for-syntax import-spec ...))
(export (for-syntax export-spec ...))
(import (for-template import-spec ...))
(export (for-template export-spec ...))
Import/export expanders that switch the phase of the import/export;
for-syntax
switches by +1, for-template
switches by -1, just like
the phi: directive.
only-in
(import (only-in import-spec id ...))
Import expander; only import identifiers id ...
from a set.
except-in except-out
(import (except-in import-spec id ...))
(export (except-out export-spec id ...))
Import and export expander; filter identifiers id ...
from a set.
rename-in rename-out
(import (rename-in import-spec (id new-id) ...))
(export (rename-out export-spec (id new-id) ...))
Import and export expander; rename specific identifiers in a set.
prefix-in prefix-out
(import (prefix-in import-spec prefix-id))
(export (prefix-out export-spec prefix-id))
Import and export expander; rename a set by applying a prefix.
struct-out
(export (struct-out struct-id ...))
Export expander; export all identifiers related with structs struct-id ...
group-in
(import (group-in prefix mod ...))
mod := id
| (id mod ...)
Imports a group of common prefix library modules.
Examples:
(import (group-in :std/misc queue rbtree))
= (import :std/misc/queue :std/misc/rbtree)
(import (group-in :std (misc queue rbtree) (net bio)))
= (import :std/misc/queue :std/misc/rbtree :std/net/bio)
(import (group-in :std sugar (srfi 1 113 133)))
= (import :std/sugar :std/srfi/1 :std/srfi/113 :std/srfi/133)
Special Evaluation Forms
eval-when-compile
(eval-when-compile expr)
Evaluates expr
when expanding in compiler context.