#>g000001 Lisp Meet Up presented by Shibuya.lisp #3参加申請しました。お金のお支払いはどこでやればよいのでしょうか?
#懇親会等があるわけでもないので実費も発生しないですね。申し込みページを確認してみたら書いてないですが、これまで実費が発生してないので書いてないのかもしれないです
#もしかしたら、初歩的な質問なのかもしれませんが、つまってしまったのでよろしくおねがいします。
#今コードを書いていて、ループの文の中でループ中の変数に依存してdoする部分でマクロをつかっているのですが、コンパイルのタイミングで先に中にマクロが展開されてしまうようで、正常に動作しません。
#(defmacro apply-select-trans (node select trans)
(let ((n (gensym)))
`(progn
(loop for ,n in (select ,select ,node)
do
(do-> ,n ,trans))
,node)))
#とマクロを定義してあって別の場所で
#(loop for stp in (group ',trans)
for selector = (car stp)
for tr = (cdr stp)
do
(%apply-select-trans
(dom:clone-node ,node t) selector tr))
#というようにつかっているのですが,先にループ内でわたしているtrというのが上のマクロで展開されてしまうようで、ループ毎のtrでなく、trというシンボル自体が渡されてしまっているようです
#実際は実行時のタイミングのtrの値を渡したいのですが、なんとか回避する方法はありますでしょうか?
#(apply-select-trans (list ,node t) selector (values tr))ってすると、実行時に do->には'(values tr)が渡っちゃうってことですかね?
#上のコードだけ見て考えると、apply-select-transじゃなくて、以前に定義した%apply-select-transのマクロは、 (do ',trans)って定義してて、差し替えてない、とか…それは無しかw
#そうですね %の部分はコピペミスです..
#そうなっちゃいます。そこをなんとかループの中のほうをわたしたいのですが...
#うーん、自分には特に変なことしてるように見えないですね do->がマクロで、quote付けてるとか位しか思い浮かばないです
#(defmacro foo (a b c) `(progn ,a ,b ,c))
(defmacro bar (i) `(loop :for ,i :from 0 :to 10 :collect (foo ,i ,i ,i)))
(bar i)
;=> (0 1 2 3 4 5 6 7 8 9 10)
#みたいなもんですよね。
#何がやりたいのかいまいち把握できない… 簡単な例で、こうマクロを使うとこういう展開形になってほしい、って示せますか。
#(defmacro do-> (node &rest trans)
`(progn
,@(loop for tra in trans
collect
(typecase tra
(symbol `(,tra ,node))
(atom `(,tra ,node))
(list `(,(car tra) ,node ,@(cdr tra)))))))
#自分だったらマクロをslimeとかで再帰的に全部展開して眺めたりはしますが....
#do->が原因か..
#do->も別に余分なquoteつけてるようには見えないけど…
#(clone-for node x (1 2 3) "p" (hoge foo))
#から(loop for x in '(1 2 3)
#(loop for x in '(1 2 3)
for nn = (make-new-node node)
collect
(loop for stp in (group '("p" (hoge "foo")))
for selector = (car stp)
for trans = (cdr stp)
do
(apply-select-trans nn selector trans)
finally (return nn)))
#clone-forってどっから出てきたの?
#あ、貼りわすれてました、すいません今はります
#(defmacro clone-for (node var lst &rest trans)
(cond
((= 1 (length trans))
`(iter (for ,var in ,lst)
(collect (-> ,node (dom:clone-node t) ,@trans))))
(t
`(progn
(loop for ,var in ',lst
for nn = (dom:clone-node ,node t)
collect
(loop for stp in (group ',trans)
for select = (car stp)
for trans = (cdr stp)
do
(apply-select-trans nn select trans)
finally (return nn)))))))
#それで、「展開されてほしい最終形」はどんな式ですか?
#(clone-for node x (1 2 3) "p" (hoge "foo"))
が
(progn
(loop for x in '(1 2 3)
for nn = (dom:clone-node node t)
collect
(loop for stp in (group '("p" (hoge "foo")))
for select = (car stp)
for trans = (cdr stp)
do
(progn
(loop for n in (select "p" node)
collect
(progn
(hoge n "foo")))
node)
(finally (return nn)))))
#do->も展開するとなるとこんな感じになってほしいです。
#transがふたつ出てきてわかりにくいんですが、clone-forのfor trans = (cdr stp) で挿入される方のtransはclone-forの引数で渡すtransとは無関係ですよね?
#そうですね
#それなら(apply-select-trans nn select ,trans)にしたらどうなりますか。
#Illigal function call errorがでました。
#("p" #:G4 '(CONTENT "baz"))
#あ、これは変数名をかえないと...
#ループの中の方の変数を tr にかえてやってみましたが、 The variable TR is unboundといわれてしまいました
#あーそりゃそうだな。(do-> #:Gxx ("p" (hoge "foo")) になりますからね。
#うーんと、clone-for中の(apply-select-trans nn select ,trans)の呼び出しを展開すると、
#(progn
(loop for #:Gxx in (select select nn)
do (do-> #:Gxx ("p" (hoge n "foo")))
nn))
#になる、ってのはいいですか? selectのところも意図どおりじゃないんじゃないかと思うんですが。
#どうも「transに渡って来た式を分解していろいろやりたい」みたいで、その分解をclone-forの展開形の内側のループでやってるっぽいですが、そのループが回るのは実行時なのでapply-select-transの展開時には「clone-forの内側のループで作ってるselectやtrans」の値は見えないですよ。最初に渡ってきたtransを分解してapply-select-transに渡したいなら、分解するコード自体がマクロ展開時に走るようにしないと。
#なるほど、そうですよね。こういうときの普通の解決方はどのようにするものなのでしょうか
#うーん、なにをやりたいのかをもう一度整理してみたらどうでしょうか。あくまで素材はclone-forに渡ってきたS式で、そのS式を操作して必要なLispコードになるS式を作るだけですよね。S式を入力としてS式を出力とする関数を書くんです。
#ありがとうございます、考えかたを再検討してみます。