マクロを使用してHeap's algorithmを実装しました。それは正常に動作していますが、必要に応じてアナフォリックまたは非アナフォリックコードを生成するように調整したいと思います。言い換えれば、私は、マクロがシーケンスの内部コピーを作成するか、マクロの外部で利用可能なシーケンスに対して作業をしたいと思っています。 ...&keyと&restをlispマクロのラムダリストに組み合わせる最良の方法は何ですか?
;; Anaphoric version
;; To make it non-anaphoric, substitute (,var (copy-seq ,vec)) for (,var ,vec)
(defmacro run-permutations (var vec &rest body)
"Executes body for all permutations of vec, which is stored in variable var"
`(let ((,var ,vec))
(labels ((generate (&optional (n (length ,var)))
(if (= n 1)
(progn ,@body)
(progn
(loop for i from 0 below (1- n)
do (progn
(generate (1- n))
(rotatef (aref ,var (if (evenp n) i 0))
(aref ,var (1- n)))))
(generate (1- n))))))
(generate))))
? (run-permutations v "123" (pprint v))
"123"
"213"
"312"
"132"
"231"
"321"
?
私はこのように働いた何かを書きたい
? (setf v "123")
? (run-permutations :anaphoric t v "123" (...do stuff...))
? v
"321"
? (setf v "123")
? (run-permutations v "123" (...do stuff...))
? v
"123"
...しかし、私は見つかっていない。
私は全く不十分で、実に恥ずかしいコードがあります&rest
と&key
またはラムダリストを書くための他の方法の満足できる組み合わせ。
私の質問です:マクロのラムダリストを解析するコードを書かずに、これを達成する方法がありますか?あるいは、もう少し標準的な(そしておそらくよりエレガントな)ソリューションがありますか?私は後者を強く疑う。
あなたのご意見は大変ありがとうございます。いつものように、コードに関する他のコメントも高く評価されています。
UPDATE
ブリリアント! body
が再帰の中から呼び出されていて、どこからでも呼び出すことができないため、n
にgensym
を使用することを選択しました。少なくとも、すべてを書き直すことはありませんでした。
また、別の機能とマイナーな最適化を追加しました。あなたは好奇心旺盛だ場合は、更新されたバージョンは次のとおりです。
(defmacro do-permutations ((var vec &key anaphoric (len (length vec))) &body body)
"Executes body for all permutations of vec, which is stored in variable var.
KEYS:
anaphoric: if defined, modifies var outside the macro, preserves it otherwise
len: number of items that will be permuted, default is the full vector"
(let ((n (gensym)))
`(let ((,var ,(if anaphoric vec `(copy-seq ,vec))))
(labels ((generate (&optional (,n ,len))
(if (= ,n 1)
(progn ,@body)
(let ((n-1 (1- ,n)))
(loop for i from 0 below n-1
do (progn
(generate n-1)
(rotatef (aref ,var (if (evenp ,n) i 0))
(aref ,var n-1))))
(generate n-1)))))
(generate)))))
最後に、私はdo
後progn
を削除しようとしたが、2式はその点で評価する必要があるので、それは動作しませんでした。正しく
あなたは正しいインデントの参照を知っていますか?私はemacsのデフォルト書式を使用していて、代替案に興味があります。 –
@JonChesterfield:ここをクリック:http://emacs.stackexchange.com/questions/30788/why-does-emacs-indent-my-lisp-loop-construct-weirdly –
ありがとう! slime-cl-indentはよく見えます。 –