► |  | The Racket Guide

1 | Welcome to Racket
2 | Racket Essentials
3 | Built-In Datatypes
4 | Expressions and Definitions
5 | Programmer-Defined Datatypes
6 | Modules
7 | Contracts
8 | Input and Output
9 | Regular Expressions
10 | Exceptions and Control
11 | Iterations and Comprehensions
12 | Pattern Matching
13 | Classes and Objects
14 | Units
15 | Reflection and Dynamic Evaluation
16 | Macros
17 | Creating Languages
18 | Concurrency and Synchronization
19 | Performance
20 | Parallelism
21 | Running and Creating Executables
22 | More Libraries
23 | Dialects of Racket and Scheme
24 | Command-Line Tools and Your Editor of Choice
| Bibliography
| Index

► | 16 | Macros

16.1 | Pattern-Based Macros
16.2 | General Macro Transformers
16.3 | Module Instantiations and Visits

▼ | 16.2 | General Macro Transformers

16.2.1 | Syntax Objects
16.2.2 | Macro Transformer Procedures
16.2.3 | Mixing Patterns and Expressions: syntax-case
16.2.4 | with-syntax and generate-temporaries
16.2.5 | Compile and Run-Time Phases
16.2.6 | General Phase Levels
16.2.7 | Code Inspectors and Syntax Taints

top ← prev up next →

##### 16.2.2`` Macro Transformer Procedures

Any procedure of one argument can be a macro transformer. As it turns out, the syntax-rules form is a macro that expands to a procedure form. For example, if you evaluate a syntax-rules form directly (instead of placing on the right-hand of a define-syntax form), the result is a procedure:

> > (syntax-rules () [(nothing) something])
> #<procedure>

Instead of using syntax-rules, you can write your own macro transformer procedure directly using lambda. The argument to the procedure is a syntax object that represents the source form, and the result of the procedure must be a syntax object that represents the replacement form:

> > (define-syntax self-as-string
> (lambda (stx)
> (datum->syntax stx
> (format "~s" (syntax->datum stx)))))

> > (self-as-string (+ 1 2))
> "(self-as-string (+ 1 2))"

The source form passed to a macro transformer represents an expression in which its identifier is used in an application position (i.e., after a parenthesis that starts an expression), or it represents the identifier by itself if it is used as an expression position and not in an application position.The procedure produced by syntax-rules raises a syntax error if its argument corresponds to a use of the identifier by itself, which is why syntax-rules does not implement an identifier macro.

> > (self-as-string (+ 1 2))
> "(self-as-string (+ 1 2))"
> > self-as-string
> "self-as-string"

The define-syntax form supports the same shortcut syntax for functions as define, so that the following self-as-string definition is equivalent to the one that uses lambda explicitly:

> > (define-syntax (self-as-string stx)
> (datum->syntax stx
> (format "~s" (syntax->datum stx))))

> > (self-as-string (+ 1 2))
> "(self-as-string (+ 1 2))"

top ← prev up next →