6.8.6 Identifier Macros

When the syntax expander sees a form in which the first element is a macro, the whole form gets passed to the macro’s syntax transformer. One may visualize this as:

(define-syntax foo foo-transformer)
(foo arg...)
;; expands via
(foo-transformer #'(foo arg...))

If, on the other hand, a macro is referenced in some other part of a form, the syntax transformer is invoked with only the macro reference, not the whole form.

(define-syntax foo foo-transformer)
foo
;; expands via
(foo-transformer #'foo)

This allows bare identifier references to be replaced programmatically via a macro. syntax-rules provides some syntax to effect this transformation more easily.

Syntax: identifier-syntax exp

Returns a macro transformer that will replace occurrences of the macro with exp.

For example, if you are importing external code written in terms of fx+, the fixnum addition operator, but Guile doesn’t have fx+, you may use the following to replace fx+ with +:

(define-syntax fx+ (identifier-syntax +))

There is also special support for recognizing identifiers on the left-hand side of a set! expression, as in the following:

(define-syntax foo foo-transformer)
(set! foo val)
;; expands via
(foo-transformer #'(set! foo val))
;; if foo-transformer is a "variable transformer"

As the example notes, the transformer procedure must be explicitly marked as being a “variable transformer”, as most macros aren’t written to discriminate on the form in the operator position.

Scheme Procedure: make-variable-transformer transformer

Mark the transformer procedure as being a “variable transformer”. In practice this means that, when bound to a syntactic keyword, it may detect references to that keyword on the left-hand-side of a set!.

(define bar 10)
(define-syntax bar-alias
  (make-variable-transformer
   (lambda (x)
     (syntax-case x (set!)
       ((set! var val) #'(set! bar val))
       ((var arg ...) #'(bar arg ...))
       (var (identifier? #'var) #'bar)))))

bar-alias ⇒ 10
(set! bar-alias 20)
bar ⇒ 20
(set! bar 30)
bar-alias ⇒ 30

There is an extension to identifier-syntax which allows it to handle the set! case as well:

Syntax: identifier-syntax (var exp1) ((set! var val) exp2)

Create a variable transformer. The first clause is used for references to the variable in operator or operand position, and the second for appearances of the variable on the left-hand-side of an assignment.

For example, the previous bar-alias example could be expressed more succinctly like this:

(define-syntax bar-alias
  (identifier-syntax
    (var bar)
    ((set! var val) (set! bar val))))

As before, the templates in identifier-syntax forms do not need wrapping in #' syntax forms.