79 lines
2.5 KiB
Racket
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]
|