Is this a conforming Common Lisp program?
(handler-bind ((condition (let ((x 0))
(lambda (c)
(declare (ignore c))
(print (incf x))))))
(signal 'condition)
(signal 'condition))
The output with SBCL (2.0.5.37) is:
1
1
The output with ABCL/CCL/ECL is:
1
2
Which behavior is defined by the Common Lisp standard?
This was a bug in SBCL, it is now fixed.
It's not exactly clear. The spec says:
Executes forms in a dynamic environment where the indicated handler bindings are in effect.
and then says
If an appropriate type is found, the associated handler is run in a dynamic environment where none of these handler bindings are visible (to avoid recursive errors).
If you interpret "run" meaning to call the function, that suggests that the handler expressions are evaluted once, when the bindings are made. This is the CCL/ABCL/ECL/LispWorks implementation, so state is maintained in the closure.
But SBCL appears to have intepreted "run" as meaning "evaluated and called". So a new closure is created each time the handler is run, and state is lost.
I suspect the intent was the first interpretation, since CL has no other "lazy" bindings.
If you change the code in the question to this:
(let ((handler
(let ((x 0))
(lambda (c)
(declare (ignore c))
(print (incf x))))))
(handler-bind ((condition handler))
(signal 'condition)
(signal 'condition)))
then SBCL behaves in the same way as the other implementations. I think this makes it fairly clear that the interpretation taken by the other implementations is the intended one, and it also provides a practical workaround for what, if that interpretation is in fact correct, is a bug in SBCL.