識別子を生成する


Tags: R6RS, マクロ

define-record-type のように、マクロへの引数として渡した識別子以外の識別子への束縛を自動的に生成してくれるマクロがあると便利なことがある。ここでは簡単な例としてタグとして使いたいシンボル sym を複数個渡し、 $$sym という識別子に束縛する define-tags マクロを考える。このようなものはシンボルを直接即値として書いてもかまわないが、一旦変数に束縛することにより処理系に綴り間違いを確認させることができるという利点が生まれる。

識別子を操作するには、 syntax->datum で一旦構文オブジェクトをデータに戻し、しかるべき操作をした上で datum->syntax で構文オブジェクトに戻す。

(import (rnrs))

(define-syntax define-tags
  (lambda (x)
    (syntax-case x ()
      ((k tags ...)
       (with-syntax (((ns ...)
                      (map (lambda (t)
                             (datum->syntax #'k
                               (string->symbol
                                (string-append "$$" (symbol->string
                                                     (syntax->datum t))))))
                           #'(tags ...))))
         #'(begin
             (define ns 'tags)
             ...))))))

(define-tags foo)

$$foo ; => foo

ただし、このようなマクロは便利である反面、プログラムの字面上に存在しない識別子を自由に束縛することができるため、混乱を招くことも多い。きちんとした基準を設けて、用法・用量を守って使うべきである。