CLで末尾呼び出し
逆引きCommon Lisp経由でCLikiのTail Recursionの説明を見て知ったんですが、
Common Lispも処理系によっては末尾呼び出しの最適化を行ってくれるんですね。
で、試しにこんなコードをコンパイルしてみました。
(defun tcall1 () (declare (optimize (space 0) (speed 0) (safety 0))) (print "test") (nanika)) (defun tcall2 () (declare (optimize (space 3) (speed 3) (safety 0))) (print "test") (nanika))
CLISPでは残念ながら最適化されませんでしたが、
SBCLを使ってみたところ、見事に最適化されました。
(出力されているコードは重要な箇所だけ切り抜いています)
* (disassemble 'tcall1) ; EF2: 8B05881EB061 MOV EAX, [#x61B01E88] ; #<NANIKA> ; EF8: 31C9 XOR ECX, ECX ; EFA: 896AFC MOV [EDX-4], EBP ; EFD: 8BEA MOV EBP, EDX ; EFF: FF5005 CALL DWORD PTR [EAX+5] * (disassemble 'tcall2) ; 64: L0: 8B0518476361 MOV EAX, [#x61634718] ; #<NANIKA> ; 6A: 31C9 XOR ECX, ECX ; 6C: FF75F8 PUSH DWORD PTR [EBP-8] ; 6F: FF6005 JMP DWORD PTR [EAX+5]
こいつはびっくりだ。
素晴らしい!この例を逆引きCLで使わせてもらえませんでしょうか。
単にちょっとしたコードを書いてdisassembleしただけですが、
それでもよければご自由にお使い下さい。
ありがとうございます!