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))"