「Land of Lisp」ではじめてfletというものを知った。
letの関数版。関数内にローカルの関数をつくれるものらしい。elispにもcl.elにあった。同じようなことはletの変数にlambdaをセットしてfuncallしてやってみたことはあるけれど。
便利そうだけど、あんまり使わないかも、とか、思っていたら。
そういやつくった関数に何か皮をかぶせた処理をいれたい、とか、よくあることだった。そういうときは別の関数をつくって皮をかぶせていたけれど、fletに押し込んでやれば、いいのか……。
なるほど。
で、fletの*HELP*を読んでいたらletfというものがあることを知る。
(setq wrk '(1 2 3)) (1 2 3) (cl-letf (((nth 1 wrk) 44)) (nth 1 wrk)) 44 wrk (1 2 3)
おっ、すげえ、と思ったけれど。
(cl-letf (((nth 1 wrk) 44)) wrk) (1 2 3)
となってしまった。
なんとなく、(1 44 3)が返ってくるような気がしていたのだけど。
もしかしたら(nth 1 wrk)の部分を44に差し替えているだけなのかな? と思ってmacroexpandしてみたら。
(macroexpand '(cl-letf (((nth 1 wrk) 44)) (nth 1 wrk))) (let* ((c (nthcdr 1 wrk)) (old (car c))) (unwind-protect (progn (setcar c 44) (nth 1 wrk)) (setcar c old))) (macroexpand '(cl-letf (((nth 1 wrk) 44)) wrk)) (let* ((c (nthcdr 1 wrk)) (old (car c))) (unwind-protect (progn (setcar c 44) wrk) (setcar c old)))
あれ?
最初のやつは44が返ってくるのに、なんで二番目のやつは(1 44 3)が返ってこないんだろう……? というか、CommonLispにはデフォルトでletfってないのかな。「undefined function: LETF」になってしまったけど。