5

マクロレットを使用して字句クロージャのようなことをする方法はありますか?私がやりたいのは、次のマクロをローカルの再帰ヘルパーにして、replでマクロを呼び出すようにリストを生成するのではなく、各組み合わせで関数を呼び出すことです。

CL-USER> (combinations nil '(1 2 3) '(4 5 6))
((1 4) (1 5) (1 6) (2 4) (2 5) (2 6) (3 4) (3 5) (3 6))

私が欲しいのは、関数と任意の数のリストを受け取り、各組み合わせで関数を呼び出すネストされたループを生成するマクロです。私はlispにかなり慣れていません。これは、「nif」クローンなどを超えて作成した最初のマクロなので、提案をいただければ幸いです。

関数を受け取るマクロでマクロをマクロレットに変換しようとしましたが、行'(nreverse(list、item、@vars))'が'(func(nreverse(list、item、@vars))に置き換えられました))'しかし、funcは未定義の変数または関数であるというエラーが表示されます。

これは元の関数です:

(defmacro combinations (vars &rest lsts)
  (with-gensyms (item)
    `(loop for ,item in ,(car lsts) ,(if (null (cdr lsts)) 'collecting 'nconcing)
       ,(if (null (cdr lsts))
            `(nreverse (list ,item ,@vars))
            `(combinations (,item ,@vars) ,@(cdr lsts))))))

これは私がマクロレットで試したものであり、未定義の関数'func'エラーが発生します。

(defmacro for-all-combonations (func &rest lst)
       (macrolet ((for-all (vars &rest lsts)
                    (with-gensyms (item)
                      `(loop for ,item in ,(car lsts) ,(if (null (cdr lsts)) 
                                                           'collecting 'nconcing)
                            ,(if (null (cdr lsts))
                                 `(func (nreverse (list ,item ,@vars)))
                                 `(for-all (,item ,@vars) ,@(cdr lsts)))))))
         (for-all nil lst)))
4

1 に答える 1

5

マクロは Common Lisp の第一級オブジェクトではないので、レキシカル クロージャに相当するものをマクロとして実際に持つことはできません。有効な Lisp プログラムであるリストを生成し、それを評価する関数を作成することによって、同様の効果を得ることができます。

ただし、それはおそらくあなたの問題に対するあまり良い解決策ではありません。Rainer Joswig が言ったように、マクロはソース コードを操作するためのものです。言語に組み込まれていない新しい構文形式が必要な場合に使用します。通常の関数で必要なものを記述できる場所では使用しないでください。

于 2010-02-21T04:06:26.667 に答える