7

define-syntaxラケットを使用して、またはdefine-syntax-ruleラケットでキャプチャ マクロを定義する最も簡単な方法は何ですか?

具体的な例として、aifCL スタイルのマクロ システムの簡単な例を次に示します。

(defmacro aif (test if-true &optional if-false)
    `(let ((it ,test))
        (if it ,if-true ,if-false)))

アイデアは、and句itの結果にバインドされるということです。素朴な音訳(オプションの代替を差し引いたもの)はtestif-trueif-false

(define-syntax-rule (aif test if-true if-false)
    (let ((it test))
       (if it if-true if-false)))

これは問題なく評価されますitが、句で使用しようとするとエラーになります。

> (aif "Something" (displayln it) (displayln "Nope")))
reference to undefined identifier: it

anaphoraは次のように実装さaifれます

(define-syntax aif
  (ir-macro-transformer
   (lambda (form inject compare?)
     (let ((it (inject 'it)))
       (let ((test (cadr form))
         (consequent (caddr form))
         (alternative (cdddr form)))
     (if (null? alternative)
         `(let ((,it ,test))
        (if ,it ,consequent))
         `(let ((,it ,test))
        (if ,it ,consequent ,(car alternative)))))))))

ir-macro-transformerしかし、Racket は定義も文書化もしていないようです。

4

3 に答える 3

11

Racket マクロは、デフォルトでキャプチャを回避するように設計されています。使用define-syntax-ruleすると、レキシカルスコープが尊重されます。

意図的に「衛生状態を崩したい」場合、伝統的にSchemeではsyntax-caseと (慎重に) を使用する必要がありますdatum->syntax

しかし、Racket で「アナフォリック」マクロを実行する最も簡単で安全な方法は、構文パラメーターと単純なdefine-syntax-rule.

例えば:

(require racket/stxparam)

(define-syntax-parameter it
  (lambda (stx)
    (raise-syntax-error (syntax-e stx) "can only be used inside aif")))

(define-syntax-rule (aif condition true-expr false-expr)
  (let ([tmp condition])
    (if tmp
        (syntax-parameterize ([it (make-rename-transformer #'tmp)])
          true-expr)
        false-expr)))

ここで構文パラメーターについて書きましたが、Eli Barzilay のDirty Looking Hygieneブログ投稿Keeping it Clean with Syntax Parametersペーパー (PDF)も読んでください。

于 2013-11-18T18:27:37.010 に答える
4

Greg Hendershott のマクロ チュートリアルを参照してください。このセクションでは、例としてアナフォリックを使用します。

http://www.greghendershott.com/fear-of-macros/Syntax_parameters.html

于 2013-11-18T18:12:04.320 に答える