From: Helmut Eller
Subject: How to write restart tests
Date: 
Message-ID: <m2wtsnteam.fsf@stud3.tuwien.ac.at>
Suppose I want to write a restart which is only visible for a certain
kind of condition.  What's the proper way to write the test function
of the restart?  Intuitively I'd write it like this:

  (define-condition foo-condition () ())
  
  (defun foo ()
    (restart-case
          (error 'foo-condition)
      (do-nothing ()
        :report "Do nothing."
        :test (lambda (c)
                (typep c 'foo-condition))
        'do-nothing-invoked)))

However this doesn't work.  E.g. the Allegro debugger doesn't show the
restart at all.  CLISP displays the restart, but when I try to invoke
it, CLISP complains that the restart is not active.

It _does_ work if I write the test as:
 
  (lambda (c) (or (not c) (typep c 'foo-condition)))

So, am I supposed to include the (not c) test? Or is this a bug in
those implementations?

Helmut.

From: Peter Seibel
Subject: Re: How to write restart tests
Date: 
Message-ID: <m3sm3bjjop.fsf@gigamonkeys.com>
Helmut Eller <········@stud3.tuwien.ac.at> writes:

> Suppose I want to write a restart which is only visible for a certain
> kind of condition.  What's the proper way to write the test function
> of the restart?  Intuitively I'd write it like this:
>
>   (define-condition foo-condition () ())
>   
>   (defun foo ()
>     (restart-case
>           (error 'foo-condition)
>       (do-nothing ()
>         :report "Do nothing."
>         :test (lambda (c)
>                 (typep c 'foo-condition))
>         'do-nothing-invoked)))
>
> However this doesn't work.  E.g. the Allegro debugger doesn't show the
> restart at all.  CLISP displays the restart, but when I try to invoke
> it, CLISP complains that the restart is not active.
>
> It _does_ work if I write the test as:
>  
>   (lambda (c) (or (not c) (typep c 'foo-condition)))
>
> So, am I supposed to include the (not c) test? Or is this a bug in
> those implementations?

Hmmm. Which version of Allegro. Using 7.0 on GNU/Linux the debugger
(well, okay, the SLIME debugger) shows the restart. I think this has
something to do with how you look for the restart. For instance:

  (handler-bind ((foo-condition
                    #'(lambda (c)
                       (format t "Looking at ~a; restart ~a and ~a~%"
                               c
                               (find-restart 'do-nothing)
                               (find-restart 'do-nothing c)))))
        (foo))

Prints:
        
  Looking at #<FOO-CONDITION @ #x72ddadba>; restart NIL and Do nothing.

Or perhaps more to the point:

  (handler-bind ((foo-condition
                 #'(lambda (c)
                    (format 
                      t
                      "Looking at ~a; restarts:~2%~{~a~%~}~%and~2%~{~a~%~}~%"
                      c
                      (compute-restarts)
                      (compute-restarts c)))))
          (foo))

Prints:
        
  Looking at #<FOO-CONDITION @ #x72716b52>; restarts:

  Abort handling SLIME request.
  Abort entirely from this (lisp) process.

  and

  Do nothing.
  Abort handling SLIME request.
  Abort entirely from this (lisp) process.


-Peter

-- 
Peter Seibel                                     ·····@gigamonkeys.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Helmut Eller
Subject: Re: How to write restart tests
Date: 
Message-ID: <m2ekevtcke.fsf@stud3.tuwien.ac.at>
Peter Seibel <·····@gigamonkeys.com> writes:

> Hmmm. Which version of Allegro. Using 7.0 on GNU/Linux the debugger
> (well, okay, the SLIME debugger) shows the restart. I think this has
> something to do with how you look for the restart. [... snipped]

The same Allegro version here.  Yeah, I know that SLIME shows the
restart, but it is still not invokable.  SLIME does basically this:

  (defun foo2 ()
    (handler-bind ((foo-condition
                    (lambda (c)
                      (invoke-restart-interactively
                       (car (compute-restarts c))))))
      (restart-case
          (error 'foo-condition)
        (do-nothing ()
          :report "Do nothing."
          :test (lambda (c)
                  (typep c 'foo-condition))
          'do-nothing-invoked))))

i.e. uses compute-restarts and then calls invoke-restart.
invoke-restart fails, probably because the restart test returns false.

To reformulate the question: should invoke-restart fail in this situation?