1

私は最近スキームを学んでおり、マクロは識別子なしでは評価できないが、ラムダ(プロシージャ)はそうできるという設計に興味があります。

たとえば、匿名ラムダを次のように使用できます。

((lambda x x) 1 2 3)

次の構文を使用してマクロを定義する必要があるようです。

(define-macro my-macro (lambda x x))

なぜそのようなメソッドがこのようなマクロを直接作成するのか、私は興味があります:

(define my-macro (macro-lambda x x))

マクロとラムダを別の型と考えれば、後者の方がエレガントかもしれません。

私の質問は次のとおりです。

  1. 何をしdefine-macroますか?
  2. マクロとラムダの根本的な違いは何ですか?
  3. スキームに匿名マクロがありますか?そうでない場合、なぜですか?
4

2 に答える 2

5

最初に、「匿名マクロ」をエミュレートする方法の例。次に、その有用性についてコメントします。

数値を表す構文オブジェクトを受け取り、入力数値の2倍を表す新しい構文オブジェクトを返すこの匿名マクロトランスフォーマーについて考えてみます。

(λ (stx) 
  (datum->syntax stx
    (* 2 (syntax->datum stx))))

次のようにテストできます。

> ((λ (stx) 
    (datum->syntax stx
      (* 2 (syntax->datum stx))))
  #'3)

結果は、6の構文オブジェクトです。

実際の数6が必要な場合は、を使用できますeval

> (eval ((λ (stx) 
          (datum->syntax stx
            (* 2 (syntax->datum stx))))
        #'3))
6

これで、匿名構文トランスフォーマーを使用して3を6に書き換えました。

匿名マクロは役に立ちますか?

匿名関数は、関数がある場所で使用されますが、必要なのは1回だけです。プログラムで同じ無名関数を2回使用する場合は、名前を付けてから2回参照する方がよいでしょう。

構文変換の場合も同じです。同じ変換が少なくとも2回必要な場合は、名前を付ける必要があります。匿名構文変換が意味をなすのは、それが1回だけ使用された場合のみです。ほとんどの場合、変換の結果を書き込むだけの方が簡単です。匿名の変換によって物事が簡単になる例は考えられません。

注:すべての例はRacketでテストされています。

于 2013-02-03T13:14:16.213 に答える
0

マクロはコンパイル時にツリーを変換しますが、残りのコードは実行時に実行されます。

一般に、両方の操作 (マクロ展開と Lisp コードの実行) は、リストを操作する手続きです。つまり、マクロとプロシージャのラムダに基本的な違いはありません。それは、それらが実行される時間だけです。これは、ネーミングなど、他のいくつかの問題が発生することを意味します。

(define ..) は実行時に実行されるため、あなたの提案は実際には機能しないと思います。

したがって、defmacro 構文は、マクロは通常の関数ですが、コンパイル時に評価されることを明確にしています。macro-lambda はむしろこれを隠します。

于 2013-02-03T12:24:20.810 に答える