1

スキーマ コンパイラは、マクロ展開中にどの関数を使用できるかをどのように決定しますか?

パターン置換を生成するだけでなく、少なくともフェンダー部分でいくつかの関数を呼び出すことができる、構文ケースのような低レベルのメカニズムを意味します

編集:

つまり、マクロ展開プロセスで通常の関数を使用する必要があります。例:

(define (twice a)
  (declare 'compile-time)
  (* 2 a))
(let-syntax ((mac (lambda (x)
                    (syntax-case x ()
                      ((_ n) (syntax (display (unsyntax (twice n)))))))))
   (mac 4))

ここで、n は数値であることがわかっており、展開中に (n の 2 倍) の評価が行われます。

4

2 に答える 2

1

すべての Scheme コンパイラは、マクロ展開によって参照される関数を決定します。あなたの場合、「let-syntax」をコンパイルすると、コンパイラーは「2回」が無料であると判断します(「let-syntax」内では構文的に範囲外です)。マクロが適用されると、'twice' 関数へのフリー リファレンスが解決されます。

異なるスキーム コンパイラは、おそらく異なる時間に自由な値の解決を実行します。「2回」を次のように定義することで、これを確認できます。

(define twice
  (begin (display 'bound')
         (lambda (x) (* 2 x))))

[あなたの場合、let-syntax では気づきにくいでしょう。define-syntax を使用し、後で '(mac 4') を使用することをお勧めします。これにより、一部のコンパイラ (guile) は、define-syntax がコンパイルされたときに「bound」を出力します。他の (ikarus) は、'(mac 4)' が展開されたときに 'bound' を出力します。]

于 2013-02-25T16:32:41.167 に答える
0

使用しているマクロ システムによって異なります。これらのシステムの一部では、展開中に通常のスキーム関数を呼び出すことができます。たとえば、明示的な名前変更マクロを使用すると、次のことができます。

(define-syntax swap!
  (er-macro-transformer
    (lambda (form rename compare?)
      ...
      `(let ((tmp ,x))
         (set! ,x ,y)
         (set! ,y tmp)))))

そうは言っても、利用できるマクロ システムは、使用しているスキームによって異なります。

于 2013-01-28T18:15:32.130 に答える