Tail optimization with labels
The lw manual states that:
http://www.lispworks.com/documentation/lw50/LWUG/html/lwuser-98.htm
9.6.3 Tail call optimization
In 64-bit LispWorks and on x86 platforms the compiler optimizes tail
calls unless
1. The compiler optimize quality debug is 3, or
2. There is something with dynamic scope on the stack, such as a
special binding, a catch or dynamic-extent allocation (so it is not
really a tail call)
In my code, I have something like this (a lot of things are removed
to isolate the things that trigger/disable tail optimization)
(defun amber2 (expr success fail)
(declare (optimize (debug 0)))
(labels ((done (val) (if val (funcall success) (funcall fail))))
(cond ((null expr) (done expr))
((atom expr) (done expr))
(t (amber2 (cdr expr) success fail)))))
;; (disassemble 'amber2)
;; =>
;; 133: FF1544289021 call [21902844] ; AMBER2
It took me a while to find out that if I replace labels with flet
then tail calls are optimized.
(defun amber1 (expr success fail)
(declare (optimize (debug 0)))
(flet ((done (val) (if val (funcall success) (funcall fail))))
(cond ((null expr) (done expr))
((atom expr) (done expr))
(t (amber1 (cdr expr) success fail)))))
;; (disassemble 'amber1)
;; 77: EBC7 jmp L1
For the above demo code it's perfectly fine to replace labels with
flet. But if I really need to call "done" within "done" recursively
then I cannot substitute labels.
Question: Does labels create any dynamic bindings? If not, is this
a bug or something that cannot be work around?
Thanks.