というわけで無限ループを書いてみる。
(format nil "~{ ~}" `(0))
おお本当に無限ループになった! format で無限ループが書けるなんてすばらしい!
まぁ一応普通の無限ループも書こう。
(defun l () (l)) (l)
こんな感じかな。
i@u ~/test/lisp> clisp forever.l *** - Program stack overflow. RESET
おやなんで末尾再帰なんとかしてないの君。 SBCL は普通に永久ループになってくれた、が、まぁとりあえずどうでもいいか。 Gauche もちゃんとループしてくれるなぁ。
(define l (lambda () (l))) (l)
あと気になったのは、
(format nil "~{ ~}" `(0))
(format nil "~{ ~}" 0)
i@u ~/test/lisp> clisp forever.l *** - The ~{ format directive requires a list argument, not 0 Current point in control string: ~{ ~} |
だってさ。なんかまぁ不正なプログラム喰わせてるのはわかるんだけど、ガチガチに標準化されてるってイメージと結構ズレるなぁ。
他の format も結構アホなものぞろいらしく。
http://raido.sakura.ne.jp/southly/rn/index.rb?1163426127.txt
まぁこのへん見て適当に
i@u ~/test/lisp> cat format.l (print (format nil "~{~D bottle~:*~P of beer~%~}" `(3 2 1))) i@u ~/test/lisp> clisp format.l "3 bottles of beer 2 bottles of beer 1 bottle of beer "
なんか複数なら複数形の s をつけるとかできるわけ。 ~{ でリスト処理に入って、 ~D で数字を処理、そんでもう一度使いたいので ~:* で前の値に戻って、 ~P で複数形の s をつけたりつけなかったり。頭おかしいなぁ。
惜しむらくは条件分岐が無いぽいことか。 SBCL の late-format.lisp とか見るとなにやら大変そうなことやってるなーと思った。
あと clisp は -c でバイトコンパイルできるんだって。
i@u ~/test/lisp> clisp -q -c format.l ;; Compiling file /home/i/test/lisp/format.l ... ;; Wrote file /home/i/test/lisp/format.fas 0 errors, 0 warnings i@u ~/test/lisp> clisp format.fas "3 bottles of beer 2 bottles of beer 1 bottle of beer "
んでネイティブコンパイルは clisp には多分無いげで、 SBCL はよくわからんくてどうでもよくなった。
を見ると native compiler 含んでるよ、って書いてあるけど、
を見てもなんかよくわからんかった。つーかコマンドラインオプションのマニュアル見ても未だによーわからんくてなにやら拒絶されてる気分だけどまぁとりあえずいいか…
追記:
そういや format のソースを見た理由を思い出した。マクロなんか関数なのかが見たかったのであった。
i@u sbcl-1.0.1/src/code> grep ' format ' target-format.lisp G defun (defun format (destination control-string &rest format-arguments)
関数ぽい。
ついでに loop も見てみる。
i@u sbcl-1.0.1/src/code> grep ' loop ' * G defmacro
loop.lisp:(sb!int:defmacro-mundanely loop (&environment env &rest keywords-and-forms)
マクロぽい。というわけで次は loop を生兵法予定。
追記2:
clisp で末尾再帰な無限ループは compile をすればいいようだ。
(defun l () (l)) (compile 'l) (l)