racket/collects/unstable/scribblings/define.scrbl
Carl Eastlund 325516556a Updated define-syntax-block to subsume define-syntax-set,
and referred to define-syntax-set in the documentation.
2011-03-18 16:54:52 -04:00

180 lines
4.7 KiB
Racket

#lang scribble/manual
@(require
scribble/eval
"utils.rkt"
(for-label
racket
unstable/define
(only-in mzlib/etc define-syntax-set)))
@title{Definitions}
@defmodule[unstable/define]
@unstable[@author+email["Carl Eastlund" "cce@racket-lang.org"]]
Provides macros for creating and manipulating definitions.
@section{Deferred Evaluation in Modules}
@defform[(at-end expr)]{
When used at the top level of a module, evaluates @scheme[expr] at the end of
the module. This can be useful for calling functions before their definitions.
@defexamples[
#:eval (eval/require 'unstable/define)
(module Failure scheme
(f 5)
(define (f x) x))
(require 'Failure)
(module Success scheme
(require unstable/define)
(at-end (f 5))
(define (f x) x))
(require 'Success)
]
}
@section{Conditional Binding}
@deftogether[(
@defform*[[(define-if-unbound x e)
(define-if-unbound (f . args) body ...)]]
@defform[(define-values-if-unbound [x ...] e)]
@defform*[[(define-syntax-if-unbound x e)
(define-syntax-if-unbound (f . args) body ...)]]
@defform[(define-syntaxes-if-unbound [x ...] e)]
)]{
Define each @scheme[x] (or @scheme[f]) if no such binding exists, or
do nothing if the name(s) is(are) already bound. The
@scheme[define-values-if-unbound] and @scheme[define-syntaxes-if-unbound] forms
raise a syntax error if some of the given names are bound and some are not.
These are useful for writing programs that are portable across versions of
Racket with different bindings, to provide an implementation of a binding for
versions that do not have it but use the built-in one in versions that do.
@defexamples[
#:eval (eval/require 'unstable/define)
(define-if-unbound x 1)
x
(define y 2)
(define-if-unbound y 3)
y
]
}
@section{Renaming Definitions}
@defform[(define-renamings [new old] ...)]{
Establishes a rename transformer for each @scheme[new] identifier,
redirecting it to the corresponding @scheme[old] identifier.
@defexamples[
#:eval (eval/require 'unstable/define)
(define-renamings [def define] [lam lambda])
(def plus (lam (x y) (+ x y)))
(plus 1 2)
]
}
@section{Forward Declarations}
@defform[(declare-names x ...)]{
Provides forward declarations of identifiers to be defined later. It
is useful for macros which expand to mutually recursive definitions, including
forward references, that may be used at the Racket top level.
}
@section{Definition Shorthands}
@defform[(define-with-parameter name parameter)]{
Defines the form @scheme[name] as a shorthand for setting the parameter
@scheme[parameter]. Specifically, @scheme[(name value body ...)] is equivalent
to @scheme[(parameterize ([parameter value]) body ...)].
@defexamples[
#:eval (eval/require 'unstable/define)
(define-with-parameter with-input current-input-port)
(with-input (open-input-string "Tom Dick Harry") (read))
]
}
@defform[(define-single-definition define-one-name define-many-name)]{
Defines a marco @scheme[define-one-name] as a single identifier
definition form with function shorthand like @scheme[define] and
@scheme[define-syntax], based on an existing macro @scheme[define-many-name]
which works like @scheme[define-values] or @scheme[define-syntaxes].
@defexamples[
#:eval (eval/require 'unstable/define)
(define-single-definition define-like define-values)
(define-like x 0)
x
(define-like (f a b c) (printf "~s, ~s\n" a b) c)
(f 1 2 3)
]
}
@section{Macro Definitions}
@defform/subs[
(define-syntax-block (macro-decl ...) body ...)
([macro-decl macro-id [macro-id expander-id]])
]{
Defines a syntax transformer for each @racket[macro-id] based on the local
definition of each @racket[expander-id]
(defaulting to @racket[macro-id]@racket[/proc]) in @racket[body ...].
Especially useful for mutually recursive expander functions and phase 1 macro
definitions. Subsumes the behavior of @racket[define-syntax-set].
@defexamples[
#:eval (eval/require 'unstable/define '(for-syntax racket/base))
(define-syntax-block
([implies expand-implies]
nand)
(define-syntax-rule (==> pattern template)
(syntax-rules () [pattern template]))
(define expand-implies (==> (_ a b) (or (not a) b)))
(define nand/proc (==> (_ a ...) (not (and a ...)))))
(implies #t (printf "True!\n"))
(implies #f (printf "False!\n"))
(nand #t #t (printf "All True!\n"))
(nand #t #f (printf "Some False!\n"))
(define-syntax-block (undefined-macro)
(define irrelevant "Whoops!"))
]
}
@section{Effectful Transformation}
@defform[(in-phase1 e)]{
Executes @scheme[e] during phase 1 (the syntax transformation phase)
relative to its context, during pass 1 if it occurs in a head expansion
position.
}
@defform[(in-phase1/pass2 e)]{
Executes @scheme[e] during phase 1 (the syntax transformation phase)
relative to its context, during pass 2 (after head expansion).
}