<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<body text="#000000" bgcolor="#ffffff">
Tim Bradshaw wrote:
<blockquote type="cite" cite="mid:F9D793AF-5FA7-4B51-BEA2-F35876677609@tfeb.org">
  <div>On 21 Jun 2010, at 22:29, Daniel Weinreb wrote:</div>
  <br class="Apple-interchange-newline">
  <blockquote type="cite"><span style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;" class="Apple-style-span">But
what if the test function isn't called at all, because<br>
the program called find-restart, compute-restart, or<br>
invoke-restart without passing any condition argument?</span></blockquote>
  <div>The test should still be called then, but with an argument of
NIL.  From FIND-RESTART:</div>
  <blockquote style="border: medium none ; margin: 0pt 0pt 0pt 40px; padding: 0px;" class="webkit-indent-blockquote">
    <div>If <i>identifier</i> is a <a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_s.htm#symbol" rel="DEFINITION" moz-do-not-send="true"><i>symbol</i></a>,
then the innermost (most recently established) <a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_a.htm#applicable_restart" rel="DEFINITION" moz-do-not-send="true"><i>applicable
restart</i></a> with that <a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_n.htm#name" rel="DEFINITION" moz-do-not-send="true"><i>name</i></a>
is returned. <a href="http://www.lispworks.com/documentation/HyperSpec/Body/a_nil.htm#nil" rel="DEFINITION" moz-do-not-send="true"><b>nil</b></a>
is returned if no such restart is found. </div>
  <div>And from the definition of "applicable restart":</div>
  <blockquote style="border: medium none ; margin: 0pt 0pt 0pt 40px; padding: 0px;" class="webkit-indent-blockquote">
    <div>2. (for no particular <a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_c.htm#condition" rel="DEFINITION" moz-do-not-send="true"><i>condition</i></a>)
an <a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_a.htm#active" rel="DEFINITION" moz-do-not-send="true"><i>active</i></a>
    <a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_h.htm#handler" rel="DEFINITION" moz-do-not-send="true"><i>handler</i></a>
for which the associated test returns <a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_t.htm#true" rel="DEFINITION" moz-do-not-send="true"><i>true</i></a>
when given <a href="http://www.lispworks.com/documentation/HyperSpec/Body/a_nil.htm#nil" rel="DEFINITION" moz-do-not-send="true"><b>nil</b></a>
as an argument.</div>
Touche.  I failed to look at the glossary.<br>
It's too bad that we have to interpret the Hyperspec this way.<br>
The description of restart-case doesn't even use the phrase<br>
"applicable handler" at all.  It could be written more clearly.<br>
But we've all run into this before.<br>
Look at this text in restart-bind (restart-case has to be considered<br>
as if it were a macro that expanded into a restart-bind, I think,<br>
although I doubt that's in the spec):<br>
  <dt><tt>:test-function</tt> </dt>
  <dd> <i>Value</i> is evaluated in the current lexical environment
and should return a <a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_f.htm#function" rel="DEFINITION"><i>function</i></a>
of one argument, a <a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_c.htm#condition" rel="DEFINITION"><i>condition</i></a>,
which returns <a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_t.htm#true" rel="DEFINITION"><i>true</i></a>
if the restart is to be considered visible.
So what does "visible" mean?  It's not in the glossary.  Do we mean<br>
visible to find-condition or visible to invoke-restart?  And it's<br>
the only use of the word "condition" in the whole definition<br>
of restart-case, with no explanation of what condition we're<br>
talking about and whether there even is one.  We can imply<br>
things from other parts of the spec, but it's certainly<br>
poor that the definition is written this way.<br>
And restart-bind says that :test-function must be a function<br>
but says nothing at all about what it does with the function.<br>
Pretty poor drafting.<br>
Interestingly, it says "The <i>function</i>, <i>interactive-function</i>,
and <i>report-function</i> are unconditionally evaluated in the
current lexical and dynamic environment prior to evaluation of the
body. Each of these <a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_f.htm#form" rel="DEFINITION"><i>forms</i></a>
must evaluate to a <a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_f.htm#function" rel="DEFINITION"><i>function</i></a>." 
If the spec were written really well, one could notice<br>
the absence of test-function and imply that it was NOT called
That's like what lawyers call "rules of construction", i.e. how you<br>
interpret the text of a law.  Anyway, we can't use that kind<br>
of rule here, since it's so clear that the drafting of the<br>
text it so sloppy.<br>
(Apologies to whomever wrote it.)<br>
In my opinion, we have to take "visible" to mean "applicable".<br>
<blockquote type="cite" cite="mid:F9D793AF-5FA7-4B51-BEA2-F35876677609@tfeb.org">
As far as I can see, the situation is reasonably clear: if FOO has a
test which returns NIL when given NIL as an argument, then
(FIND-RESTART 'FOO) should return NIL.</blockquote>
I agree.<br>
<blockquote type="cite" cite="mid:F9D793AF-5FA7-4B51-BEA2-F35876677609@tfeb.org">  The problem seems to be, I think, whether INVOKE-RESTART
should cause the test to be run as well, and I think the answer ought
to be as follows.
  <div>I think (INVOKE-RESTART 'FOO) is essentially (INVOKE-RESTART
(FIND-RESTART 'FOO)_ which is essentially (from above) (INVOKE-RESTART
(FIND-RESTART 'FOO NIL)).  So in that case, INVOKE-RESTART will
(indirectly) call the test, with NIL as its argument.</div>
I agree; it would be weird if that were not the case.<br>
<blockquote type="cite" cite="mid:F9D793AF-5FA7-4B51-BEA2-F35876677609@tfeb.org">
  <div>But if <i>have</i> a restart object (not just a symbol which
may or may not name one), then I think INVOKE-RESTART should just get
on and run it: it's too late now to run the test.</div>
But only if it is "valid"; that's clear from the spec, as long as you
figure out what "valid" means.  So I disagree that it should always<br>
run something.  Clearly if that restart isn't in the dynamic
environment (is not "active")<br>
at all, you can't run it.  I think you're saying that if it IS in the
environment (active), we should restart, and not run the test.  I agree<br>
that the test happens at the find-restart level, not the<br>
invoke-restart level; I think the spec is quite clear about that.<br>
So "applicable" (which is a synonym for "visible") can't have anything<br>
to do with the behavior of invoke-handler.<br>
<blockquote type="cite" cite="mid:F9D793AF-5FA7-4B51-BEA2-F35876677609@tfeb.org">
  <div>  This allows the possibility of getting hold of a restart under
false pretences, but I think that's something one can not avoid.</div>
I think I know what you mean, but I'm not sure I can think of<br>
a scenario where something evil happens.  If the restart<br>
isn't "valid", nothing unexpected happens. "Valid" obviously<br>
includes being in the dynamic environment; the question<br>
is whether there might be some additional criterion.<br>
But that criterion can't have anything to do with<br>
test functions in restart-case<br>
<blockquote type="cite" cite="mid:F9D793AF-5FA7-4B51-BEA2-F35876677609@tfeb.org">
  <div>As I understand it that's what Kent Pitman is saying in the mail
quoted previously, and I think that is right.</div>
Re "continue", it's clear that anything that takes an optional condition<br>
argument is using it for find-condition purposes.<br>
Kent's paragraph about invoke-restart seems to be confused,<br>
because he talks about "if a symbol is passed", clearly<br>
meaning a condition name, but invoke-restart does<br>
not take such an argument.  He's misremembering.<br>
Easy to do in this case, in my opinion!<br>
But later he says what I asserted above:<br>
"So it has to be the case that it's the error<br>
system (well, find-restart) that is doing all this calling of the<br>
test, and it's the invoker that is actually running the restart."<br>
However, then he says:<br>
"Once you invoke the restart, it's going to run whether it's the right<br>
one to execute or not, and in my opinion it might signal an error not<br>
return NIL if you invoke a wrong one"<br>
But how can it possibly know if it's a "wrong" one?<br>
The condition that would have to be passed to<br>
the test function isn't there.<br>
I think the scenario causing the worry is that there<br>
IS a relevant condition (whatever that means;<br>
as I said above, restart-bind's definition is<br>
awful; whatever...), you should have passed<br>
that condition to find-restart, but you didn't,<br>
and the test would have returned nil had<br>
you done so, and then you do invoke-restart.<br>
The restart is coded such that it is allowed<br>
to assume that the test passed.  That is<br>
the key point that hasn't been articulated<br>
yet, as far as I remember.  Your invoke-restart<br>
could invalidate that assumption, causing<br>
the handler to have a bug.<br>
<blockquote type="cite" cite="mid:F9D793AF-5FA7-4B51-BEA2-F35876677609@tfeb.org">
  <div>This is not the behaviour that CCL has: INVOKE-RESTART calls the
test, regardless of whether you call it with a restart object, or a
symbol naming one.  I think that's wrong (though this is obviously just
my opinion).</div>
I don't think invoke-restart should ever call any tests, if<br>
you want to follow the spec.  I agree with Gary that<br>
it's better to follow the spec that make your own<br>
subjective decisions of what would have been better,<br>
at least because portability is an important goal.<br>
Unfortunately I forgot to save the original message<br>
of this thread so I can't remember the particular<br>
case.  For restart-case, it doesn't look to me from<br>
the CCL sources as if it's calling a function, but<br>
for a restart-bind, it does seem to be calling a function.<br>
I think the fact that invoke-restart does not<br>
call the unexported function applicable-restart-p<br>
should be a hint that invoke-restart is not in<br>
the business of worrying whether a restart<br>
is applicable.<br>
<blockquote type="cite" cite="mid:F9D793AF-5FA7-4B51-BEA2-F35876677609@tfeb.org">
  <div>It seems to me that this issue is getting confused because, in
some of the earlier examples posted here, what was being done was
(INVOKE-RESTART <symbol-naming-restart>), and I think in that
case (from above) that the test <i>should</i> be invoked, as the
restart is looked up (in other words, if I just have a name, I don't
have a restart yet).</div>
It looks to me, from the CCL sources (%active-restart), as if<br>
it always runs the test, regardless of whether the<br>
restart designator is a symbol or a restart.<br>
So, from a CCL point of view, I think %active-restart<br>
should not run the function; only applicable-restart-p<br>
should do that.<br>
(I may be misinterpreting the code, though.  I'd test<br>
it but I don't have time, sorry.)<br>
-- Dan<br>
<blockquote type="cite" cite="mid:F9D793AF-5FA7-4B51-BEA2-F35876677609@tfeb.org">
  <div>However I have not followed this really carefully, or thought
about it enough.</div>