-2

この構文を読み取ることができるメタ循環インタープリターの関数 defmacro を作成する必要があります。

pseudoscheme> (defmacro (minus x y) (list ‘- y x))
MINUS


pseudoscheme> (expand-macro '(minus 3 2))
(- 3 2)

これを使用する場合:

(defmacro my-defmacro ((name &rest args) &body  body)
    (let ((form (gensym))(env (gensym)))
        (progn 
        `(setf (macro-function ',name)    
            (lambda (,form ,env))
                (destructuring-bind ,args (rest, form) ,@body))
        name
        )   
    )
)

その後:

(my-defmacro (min a b)(list '- a b))

次のエラーが表示されます。

Error: The variable MIN is unbound.

理由がわかりません。

-----編集済み-----これを使用する場合:

(defmacro my-defmacro ((name &rest args) &body  body)
    (let ((form (gensym))(env (gensym)))
        `(progn (setf (macro-function ',name)
            (lambda (,form ,env))
                (destructuring-bind ,args (rest, form) ,@body))
         ',name)    
    )
)

その後:

(my-defmacro (min a b)(list '- a b))

次のエラーが表示されます。

Error: Odd number of args to SETF: ((MACRO-FUNCTION (QUOTE PLUS)) (LAMBDA (#:G786 #:G787)) (DESTRUCTURING-BIND (A B) (REST #:G786) (LIST # A B)))
4

2 に答える 2

0

あなたmy-defmacroはCLシステムをホストするために機能しますが、インタープリターにマクロ機能が必要なように感じますが、これでは機能しません。(ただし、インタープリター環境がグローバル ホスト実装環境である場合を除きますが、それは多くの課題となります)

エバリュエーターで複合プロシージャをどのように実行するかはわかりませんが、私のエバリュエーターが を取得する(lambda (x) (+ x x))と、 に変わり(compound-procedure <env> (x) (+ x x))ます。私のマクロは、最初の要素がcompound-syntax.

評価されたすべての演算子には、それが何であるかを示すタグ (プリミティブ構文、プリミティブ手順、複合構文、複合手順のいずれか) があり、それら 4 を処理する一般的な方法だけが必要です。

複合プロシージャと複合構文の実際の違いは、引数がプロシージャに対して評価され、複合構文では結果が評価されることです。

そう。((lambda (x) (+ xx)) 5) が機能するように実装しましたか? それでは、マクロもほぼ実装します。もちろん、これはコンパイラーには当てはまりません。このアプローチでは、クロージャーが作成されたときにコードが一度拡張されるのではなく、実行されるたびにコードが拡張されるからです。(とにかく最初のバージョンで最適化を行う方法はありません)

于 2013-09-29T00:38:42.153 に答える
0

あなたの「編集されたコード」には、間違った括弧があります:

(defmacro my-defmacro ((name &rest args) &body  body)
    (let ((form (gensym))(env (gensym)))
        `(progn (setf (macro-function ',name)
            (lambda (,form ,env))                    ;; <== HERE
                (destructuring-bind ,args (rest, form) ,@body))
         ',name)    
    )
)

これにより、setf3 つのサブフォームが作成されます。次のように書き直します (標準の Lisp フォーマットを使用しながら):

(defmacro my-defmacro ((name &rest args) &body  body)
  (let ((form (gensym))
        (env  (gensym)))
    `(progn (setf (macro-function ',name)
                  (lambda (,form ,env)
                    (destructuring-bind ,args (rest, form) 
                      ,@body)))
            ',name)))   
于 2013-09-29T15:59:19.930 に答える