From: Norman Werner
Subject: :test argument of restart-case
Date: 
Message-ID: <1155238812.396645.305720@h48g2000cwc.googlegroups.com>
Hello,

The following code seems to show, that the
test-function of restart-case is called with NIL as its argument:

(handler-bind  ((error #'(lambda (x) (invoke-restart 'MY-RESTART))))
       (restart-case (error "DUMMY ERROR")
	       (MY-RESTART ()  :test (lambda (c) (if c
						     t
						   (progn
						     (format t "Test Function was called with NIL")
						     NIL)))  t)))


However the relevant Hyperspec Section implies that it should be called

with the  condition:

<quote>
The value supplied by :test value must be a suitable argument to
function. (function value) is evaluated in the current lexical
environment. It should return a function of one argument, the
condition, that returns true if the restart is to be considered
visible.
</quote>

Can anyone explain this to me? Am I misinterpreting the standard or
is it an implementation problem (i am using sbcl here)


Thanks in advance

Norman Werner

PS:
I am aware of this 2005-thread:
http://coding.derkeiler.com/Archive/Lisp/comp.lang.lisp/2005-04/msg01437.html
as well as
http://www.lispworks.com/documentation/HyperSpec/Issues/iss075_w.htm
However they don't seem to answer my question.

From: ········@gmail.com
Subject: Re: :test argument of restart-case
Date: 
Message-ID: <1155258216.589460.131540@p79g2000cwp.googlegroups.com>
Norman Werner wrote:
> Hello,
>
> The following code seems to show, that the
> test-function of restart-case is called with NIL as its argument:
>
> (handler-bind  ((error #'(lambda (x) (invoke-restart 'MY-RESTART))))
>        (restart-case (error "DUMMY ERROR")
> 	       (MY-RESTART ()  :test (lambda (c) (if c
> 						     t
> 						   (progn
> 						     (format t "Test Function was called with NIL")
> 						     NIL)))  t)))
>
>
> However the relevant Hyperspec Section implies that it should be called
>
> with the  condition:
>
> <quote>
> The value supplied by :test value must be a suitable argument to
> function. (function value) is evaluated in the current lexical
> environment. It should return a function of one argument, the
> condition, that returns true if the restart is to be considered
> visible.
> </quote>

hey Norman,

I'm not on a computer with lisp installed, but did you try supplying a
parameter at XX in (MY-RESTART (XX) ...

if I remember correctly (my-restart () ... is equivalent to (my restart
(#1=#:xx) (declare (ignore #1#) ... this could be the problem...

hth

Nick
From: ········@gmail.com
Subject: Re: :test argument of restart-case
Date: 
Message-ID: <1155259485.739446.70490@i3g2000cwc.googlegroups.com>
> > (handler-bind  ((error #'(lambda (x) (invoke-restart 'MY-RESTART))))
> >        (restart-case (error "DUMMY ERROR")
> > 	       (MY-RESTART ()  :test (lambda (c) (if c
> > 						     t
> > 						   (progn
> > 						     (format t "Test Function was called with NIL")
> > 						     NIL)))  t)))

also (handler-bind ((error #'(lambda (x) (invoke-restart 'MY-RESTART
x)...

hth

Nick
From: Norman Werner
Subject: Re: :test argument of restart-case
Date: 
Message-ID: <1155277728.310787.308700@74g2000cwt.googlegroups.com>
········@gmail.com schrieb:

> > > (handler-bind  ((error #'(lambda (x) (invoke-restart 'MY-RESTART))))
> > >        (restart-case (error "DUMMY ERROR")
> > > 	       (MY-RESTART ()  :test (lambda (c) (if c
> > > 						     t
> > > 						   (progn
> > > 						     (format t "Test Function was called with NIL")
> > > 						     NIL)))  t)))
>
> also (handler-bind ((error #'(lambda (x) (invoke-restart 'MY-RESTART
> x)...
>
> hth
>
> Nick

Thanks for the  answer -
I tried it - but it did not  help.

AFAIK the argument to the restart is independent
to the test - whether the restart is visible. 



Norman
From: Geoffrey Summerhayes
Subject: Re: :test argument of restart-case
Date: 
Message-ID: <1155330764.097357.62480@p79g2000cwp.googlegroups.com>
Norman Werner wrote:
> ········@gmail.com schrieb:
>
> > > > (handler-bind  ((error #'(lambda (x) (invoke-restart 'MY-RESTART))))
> > > >        (restart-case (error "DUMMY ERROR")
> > > > 	       (MY-RESTART ()  :test (lambda (c) (if c
> > > > 						     t
> > > > 						   (progn
> > > > 						     (format t "Test Function was called with NIL")
> > > > 						     NIL)))  t)))
> >
> > also (handler-bind ((error #'(lambda (x) (invoke-restart 'MY-RESTART
> > x)...
> >
> > hth
> >
> > Nick
>
> Thanks for the  answer -
> I tried it - but it did not  help.
>
> AFAIK the argument to the restart is independent
> to the test - whether the restart is visible.

To be honest, I don't see why the test is even being called. The error
is going to the bound
handler which is invoking the restart, it won't be visible anyway, why
call the test function?
AFAICT, getting a NIL indicates the restart was invoked rather than
handled interactively.

CL-USER 1 > (restart-case
                (error "foo")
              (test ()
                    :test (lambda (c) (format t "~&got:~A~%" c) t)))
got:foo

Error: foo
  1 (continue) TEST
  2 (abort) Return to level 0.
  3 Return to top loop level 0.

Type :b for backtrace, :c <option number> to proceed,  or :? for other
options

CL-USER 2 : 1 > :c 1
NIL

CL-USER 3 > (restart-case
                (invoke-restart 'test 7)
              (test (x)
                    :test (lambda (c) (format t "~&got:~A~%" c) t)
                    x))
got:NIL
7

---
Geoff
From: ········@gmail.com
Subject: Re: :test argument of restart-case
Date: 
Message-ID: <1155333257.149673.283720@b28g2000cwb.googlegroups.com>
Norman Werner wrote:
> ········@gmail.com schrieb:
>
> > > > (handler-bind  ((error #'(lambda (x) (invoke-restart 'MY-RESTART))))
> > > >        (restart-case (error "DUMMY ERROR")
> > > > 	       (MY-RESTART ()  :test (lambda (c) (if c
> > > > 						     t
> > > > 						   (progn
> > > > 						     (format t "Test Function was called with NIL")
> > > > 						     NIL)))  t)))
> >
> > also (handler-bind ((error #'(lambda (x) (invoke-restart 'MY-RESTART
> > x)...
> >
> > hth
> >
> > Nick
>
> Thanks for the  answer -
> I tried it - but it did not  help.
>
> AFAIK the argument to the restart is independent
> to the test - whether the restart is visible.

The HyperSpec says of the :test value given to
HANDLER-CASE/HANDLER-BIND:

"The value supplied by :test value must be a suitable argument to
function. (function value) is evaluated in the current lexical
environment. It should return a function of one argument, the
condition, that returns true if the restart is to be considered
visible."

the noteworthy part of that being that the argument to this is a
_condition_.

my guess is that the behavior of this function is more specifically
defined as taking an argument that may be (a) a condition or (b) NIL if
none is supplied

thus it would be relevent in this instance since  INVOKE-RESTART
doesn't take an optional condition argument (like FIND-RESTART), so

    (handler-bind ((error #'(lambda (x) (invoke-restart 'MY-RESTART))))
    ...

is finding the appropriate restart like

    ...#'(lambda (x) (invoke-restart (find-restart 'MY-RESTART)))

intead of

    ...#'(lambda (x) (invoke-restart (find-restart 'MY-RESTART x)))

thus it makes sense given this supposition that the "condition"
argument in this case could be NIL

it's obvious though that if this is indeed the case this passage should
have been worded differently and this behavious explicitly pointed
out... (though when you think about it, it is an example of the
expressiveness of Lisp: it allows you to have a hand in specifying what
restart you want to be visible even when there is no condition
involded!)

that being said I think there is still something skrewey going on with
your example... (I'm using ACL 8.0 not SBCL)

(handler-bind ((error #'(lambda (x)
                             (invoke-restart 'my-restart))))
   (restart-case (error "dummy error")
      (my-restart () :test (lambda (c)
                               (print c)
                                nil
                  'restart-2)
      (my-restart () :test (lambda (c)
                               (print c)
                                t
                  'restart-2)))

gets me

NIL
NIL
=> 'RESTART-2

showing that both test functions were called with NIL and that the
second version of my-restart was chosen based on the return value of
the :test functions...

but if I explicitly call FIND-RESTART supplying the optional condition
arg

(handler-bind ((error #'(lambda (x)
                            (invoke-restart (prog1
                                               (find-restart
'my-restart x)
                                               (print "found restart"))
   (restart-case (error "dummy error")
      (my-restart () :test (lambda (c)
                               (print c)
                                nil
                  'restart-2)
      (my-restart () :test (lambda (c)
                               (print c)
                                t
                  'restart-2)))

I get

#<SIMPLE-ERROR @ #xdc282>
#<SIMPLE-ERROR @ #xdc282>
"found restart"
NIL
NIL
=> RESTART-2

suggesting test is being called by both FIND-RESTART and
INVOKE-RESTART, and indeed

(handler-bind ((error #'(lambda (x)
                            (invoke-restart 'my-restart))))
   (restart-case (error "dummy error")
      (my-restart () :test (lambda (c)
                               c)
                  'restart-2)
      (my-restart () :test (lambda (c)
                               (not c))
                  'restart-2)))

throws an error

Nick
From: Norman Werner
Subject: Re: :test argument of restart-case
Date: 
Message-ID: <1155340800.366260.174130@i42g2000cwa.googlegroups.com>
Thanks for youre reply which helped a lot.
Just to make sure - I understood everything correctly
(and to help future users with the same problem)
let me formulate this working hypothesis:

1)  the usable restarts have to be determined at runtime
     by the function FIND-RESTART.
2) This function takes a condition as optional argument
     which serves as input to the :test  function
3) when invoke-restart is called with a restart-designator
     (eg. a symbol) instead of a restart it calls find-restart
     - BUT WITHOUT THE OPTIONAL ARGUMENT.

Or by Example:

GOOD:
(handler-bind
 ((error #'(lambda (x) (invoke-restart (find-restart 'my-restart x)))))
 (restart-case (error "DUMMY ERROR")
	       (MY-RESTART ()  :test (lambda (c) c)  'OK)))

BAD:
(handler-bind
 ((error #'(lambda (x) (invoke-restart 'my-restart))))
 (restart-case (error "DUMMY ERROR")
	       (MY-RESTART ()  :test (lambda (c) c)  'OK)))



Norman
From: Geoffrey Summerhayes
Subject: Re: :test argument of restart-case
Date: 
Message-ID: <1155358531.909295.167580@i3g2000cwc.googlegroups.com>
Norman Werner wrote:
> Thanks for youre reply which helped a lot.
> Just to make sure - I understood everything correctly
> (and to help future users with the same problem)
> let me formulate this working hypothesis:
>
> 1)  the usable restarts have to be determined at runtime
>      by the function FIND-RESTART.
> 2) This function takes a condition as optional argument
>      which serves as input to the :test  function
> 3) when invoke-restart is called with a restart-designator
>      (eg. a symbol) instead of a restart it calls find-restart
>      - BUT WITHOUT THE OPTIONAL ARGUMENT.
>
> Or by Example:
>
> GOOD:
> (handler-bind
>  ((error #'(lambda (x) (invoke-restart (find-restart 'my-restart x)))))
>  (restart-case (error "DUMMY ERROR")
> 	       (MY-RESTART ()  :test (lambda (c) c)  'OK)))
>
> BAD:
> (handler-bind
>  ((error #'(lambda (x) (invoke-restart 'my-restart))))
>  (restart-case (error "DUMMY ERROR")
> 	       (MY-RESTART ()  :test (lambda (c) c)  'OK)))

Since you're writing a test function, how about:

(handler-bind
  ((error (lambda (error)
            (let ((restart (find-restart 'my-restart error)))
              (if restart
                  (invoke-restart restart)
                (continue error))))))
  ...)

---
Geoff