[Openmcl-devel] INVOKE-RESTART bug

Stelian Ionescu sionescu at cddr.org
Sat Jun 19 12:39:59 PDT 2010


On Thu, 2010-06-03 at 05:24 -0600, Gary Byers wrote:
> The restart isn't applicable: when called with NIL as an argument, its
> test function returns NIL.
> 
> INVOKE-RESTART is supposed to signal a CONTROL-ERROR if the restart
> isn't valid.  Some implementations (LispWorks and SBCL) that I looked
> at appear to consider inapplicable restarts to be valid; others (Allegro,
> CLISP, and CCL) don't.  I lean towards believing that the latter interpretation
> is correct (both because it's what I'm used to and because I find the concept
> of "valid, but inapplicable restarts" a little hard to believe in), but the
> language that the spec uses seems unfortunately vague.  (The term "valid restart"
> doesn't seem to be defined anywhere; interpreting "valid restart" to mean "active,
> though not necessarily applicable restart" isn't totally unreasonable, either.
> 
> The problem with that latter interpretation is that a test function has to
> return T if called with NIL as an argument in order to be considered applicable.
> (It's not clear that restart test functions that don't accept NIL are particularly
> useful in that interpretation, but the somewhat awkward idiom:
> 
>   :test (lambda (c) (or (null c) (typep c 'some-condition)))
> 
> is likely necessary in practice, given that implementations behave differently
> when the (NULL C) case returns false.

I'd rather not start arguing about the interpretation of the standard,
but think of what is the most useful choice of implementation.

With the design choice of CCL et al., this can happen:

(define-condition foo-error (error) ())

(defun maybe-signal-foo (x)
  (restart-case
      (if x (error 'foo-error) (error "Foo"))
    (ignore-foo ()
      :report "Ignore FOO error"
      :test (lambda (c) (or (null c) (typep c 'foo-error)))
      'yay)))

(defun trigger-bug (x)
  (handler-bind ((error
                  (lambda (e)
                    (invoke-restart 'ignore-foo))))
    (maybe-signal-foo x)))

> (trigger-bug nil)
YAY


It's arguable that this code is incorrect because it invokes IGNORE-FOO
always, not just if the condition is a FOO-ERROR and that the programmer
should be more careful, but that practically means that the programmer
must execute the restart-test in his head when writing the code, making
the restart-test useless

My guess is that many of the original implementors disliked having to
always use
(invoke-restart (find-restart <name> <condition>) ...) - which would be
the result of the choice for which I'm arguing, but that's besides the
point. As a library writer, I want the guarantee that the IGNORE-FOO
restart will only be invoked as a consequence of a FOO-ERROR, and
Clozure doesn't offer this guarantee

-- 
Stelian Ionescu a.k.a. fe[nl]ix
Quidquid latine dictum sit, altum videtur.
http://common-lisp.net/project/iolib
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part
URL: <https://lists.clozure.com/pipermail/openmcl-devel/attachments/20100620/5e8e0eb2/attachment.bin>


More information about the Openmcl-devel mailing list