racket/pkgs/racket-doc/scribblings/guide/module-macro.scrbl

79 lines
2.5 KiB
Racket

#lang scribble/doc
@(require scribble/manual
scribble/example
"guide-utils.rkt")
@(define noisy-eval (make-base-eval))
@title[#:tag "module-macro"]{Modules and Macros}
Racket's module system cooperates closely with Racket's @tech{macro}
system for adding new syntactic forms to Racket. For example, in the
same way that importing @racketmodname[racket/base] introduces syntax
for @racket[require] and @racket[lambda], importing other modules can
introduce new syntactic forms (in addition to more traditional kinds
of imports, such as functions or constants).
We introduce macros in more detail later, in @secref["macros"], but
here's a simple example of a module that defines a pattern-based
macro:
@examples[
#:eval noisy-eval
#:no-result
(module noisy racket
(provide define-noisy)
(define-syntax-rule (define-noisy (id arg ...) body)
(define (id arg ...)
(show-arguments (quote id) (list arg ...))
body))
(define (show-arguments name args)
(printf "calling ~s with arguments ~e" name args)))
]
The @racket[define-noisy] binding provided by this module is a
@tech{macro} that acts like @racket[define] for a function, but it
causes each call to the function to print the arguments that are
provided to the function:
@examples[
#:label #f
#:eval noisy-eval
(require 'noisy)
(define-noisy (f x y)
(+ x y))
(f 1 2)
]
Roughly, the @racket[define-noisy] form works by replacing
@racketblock[(define-noisy (f x y)
(+ x y))]
with
@racketblock[(define (f x y)
(show-arguments 'f (list x y))
(+ x y))]
Since @racket[show-arguments] isn't provided by the @racket[noisy]
module, however, this literal textual replacement is not quite right.
The actual replacement correctly tracks the origin of identifiers like
@racket[show-arguments], so they can refer to other definitions in the
place where the macro is defined---even if those identifiers are not
available at the place where the macro is used.
There's more to the macro and module interaction than identifier
binding. The @racket[define-syntax-rule] form is itself a macro, and
it expands to compile-time code that implements the transformation
from @racket[define-noisy] into @racket[define]. The module system
keeps track of which code needs to run at compile and which needs to
run normally, as explained more in @secref["stx-phases"] and
@secref["macro-module"].
@; ----------------------------------------------------------------------
@close-eval[noisy-eval]