Hi Marc!<br><br><div class="gmail_quote">2013/3/18 Marc Feeley <span dir="ltr"><<a href="mailto:feeley@iro.umontreal.ca" target="_blank">feeley@iro.umontreal.ca</a>></span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<div>The problem I see with the approach you propose (whether it uses a parameter or a port specific flag) is that the semantics of an "io-error" is vague.  What is an IO error?  The definition is important because exceptions that are IO errors are going to be processed using this new mechanism, and non-IO exceptions will use a different mechanism (normal exception handling).</div>



<br>
The approach I propose does not have this problem because the programmer has complete control over the definition of an IO error.  The exception object can be inspected to see if it qualifies as an IO error and an appropriate action can be taken.  The definition of IO error can depend on the type of port, the type of primitive which caused the exception (read-u8, read-char, read), etc.<br>



<span><font color="#888888"><br>
Marc<br>
<br>
</font></span></blockquote></div><br><div>Aha. To really get this, there are two quite fundamental things about the applicability of the with-exception-handler possibility that I maybe don't get yet or at least would benefit of clarification, can we have a look at it?</div>

<div><br></div><div>Also last a question re semantics of io-error.</div><div><br></div><div><br></div><div><br></div><div>So, for the with-exception-handler mechanism to work out, it needs to go together with other use of exception handling use that's being done in the same scope.</div>

<div><br></div><div>In a setup where there's another exception handler *outside* the IO with-exception-handler, there would be no issue as the IO w.e.h. 's handler would be invoked first for any exception that occurs, and do its matching and handling.</div>

<div><br></div><div>In a setup where the other exception handler is made *inside* the IO w.e.h. though, any IO exception that arises within that exception handler will be picked up by it first, and for the IO w.e.h. thing to work out, that handler needs to be able to pass on the exception to the parent exception handler (which is the IO w.e.h.) completely in its original shape, in such a way that if the IO w.e.h. handler returns a value, that will be passed as return value to the original |raise| call.</div>

<div><br></div><div>An example of this would be a web-based PI calculator that uses exception handling locally in its PI calculate request thunk to pick up invalid user input.</div><div><br></div><div>So let's ask how this could be done.</div>

<div><br></div><div><div>Let's say below that we have a procedure <font face="courier new, monospace">(install-io-w.e.h. port thunk)</font> that installs the IO w.e.h. that makes IO primitives return #f on exception, so that thunk is invoked with that w.e.h. installed.</div>

</div><div><br></div><div>Then, we have application logics <font face="courier new, monospace">(logics)</font> that, aside from using IO, internally uses exception handling.</div><div><br></div><div>So a setup something like,</div>

<div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><font face="courier new, monospace">(define (logics)</font></div><div><font face="courier new, monospace">  (with-exception-catcher</font></div>

<div><font face="courier new, monospace">    (lambda (e) "Logics failed due to invalid user input!")</font></div><div><font face="courier new, monospace">    (lambda ()</font></div><div><span style="font-family:'courier new',monospace">      (pp (read-u8 broken-port))</span></div>

<div><span style="font-family:'courier new',monospace">      (/ 0 0) ; This is to simulate an exception due to invalid user input.</span></div><div><span style="font-family:'courier new',monospace">      )))</span></div>

<div><font face="courier new, monospace">(install-io-w.e.h. broken-port logics)</font></div></blockquote><div><br></div><div>The desired behavior here is to print <font face="courier new, monospace">#f</font> to the console and for logics to then return <span style="font-family:'courier new',monospace">"Logics failed due to invalid user input!"</span><font face="arial, helvetica, sans-serif">.</font></div>

<div><br></div><div>The issue now becomes, how would this local exception handler need to be implemented as for this to work out.<br><br><br>The local exception handler needs to be specific about what kind of error it looks for as to know which to handle locally and which to re-raise. This might be a complete PITA in some situations as you're looking for a catch-all behavior, as in the example above!</div>

<div><br></div><div>Perhaps the order of exception handlers could be tweaked somehow, so that the IO w.e.h. would get highest priority or something, though how could that be made as a 'clean' abstraction? I mean, who's in a place to claim at a general level that one exception is of higher prio than another? - different classes could be introduced, like, "user exceptions" and "io exceptions" or "system exception" (this would lead to an at least almost functional equivalent of the port specific flag solution, just with a more indirect code path!), or, the exception matching procedure could be exported to a separate mechanism, and the exception handler claiming the highest specificity in the matching would get to handle it e.g. <font face="courier new, monospace">(with-exception-handler exception-match exception-handler thunk)</font> where exception-match takes an exception argument e and returns how well it matches the exception, i duno as a boolean or 0-10 or a symbol.</div>

<div><br></div><div>Or, a global parameter object <font face="courier new, monospace">|is-nonlocal-exception?|</font> could be introduced that any exception handler is free to invoke as to check if it should re-raise the exception, and to overlap.. hmm, a more general solution would be better.</div>

<div><br></div><div>Do you see any general solution to this specificity problem?</div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div>Now to get to the next thing, let's just presume there's a solution to this and we represent it in this example as a <span style="font-family:'courier new',monospace">(if (is-nonlocal-exception? e) (raise e)</span><span style="font-family:'courier new',monospace"> </span>condition in the local exception handler, again not because this would necessarily represent a general solution but just to get on to the next thing in the reasoning; so now we have</div>

<div><br></div><div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face="courier new, monospace">(define (logics)</font></div><div><font face="courier new, monospace">  (with-exception-catcher</font></div>

<div><font face="courier new, monospace">    (lambda (e) (if (is-nonlocal-exception? e) (raise e) "Logics failed due to invalid user input!"))</font></div><div><font face="courier new, monospace">    (lambda ()</font></div>

<div><span style="font-family:'courier new',monospace">      (pp (read-u8 broken-port))</span></div><div><span style="font-family:'courier new',monospace">      (/ 0 0) ; This is to simulate an exception due to invalid user input.</span></div>

<div><span style="font-family:'courier new',monospace">      )))</span></div><div><font face="courier new, monospace">(install-io-w.e.h. broken-port logics)</font></div><div><font face="courier new, monospace"><br>

</font></div></blockquote></div><div><br></div><div>Now, how do you make this *parent* exception handler (the IO w.e.h.) that got the exception passed to it, able to pass a return value to the original <font face="courier new, monospace">|raise|</font> call?</div>

<div><br></div><div>This is required for the exception handling-based IO error handling behavior we're looking for to work.</div><div><br></div><div>The problem reduces to</div><div><br></div><div><blockquote style="margin:0 0 0 40px;border:none;padding:0px">

<div><font face="courier new, monospace">(define (logics) (raise "Please return 'properly-handled!"))</font></div><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">(define (proxy-exception-handler/catcher2 thunk) (lambda () (with-exception-catcher (lambda (e) (raise e)) thunk)))</font></div>

<div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">(define (proxy-exception-handler/catcher1 thunk) (lambda () (with-exception-handler (lambda (e) (raise e)) thunk)))</font></div>

<div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">(define (parent-exception-handler thunk)</font><span style="font-family:'courier new',monospace"> (continuation-capture </span><span style="font-family:'courier new',monospace">(lambda (cont) </span><font face="courier new, monospace">(with-exception-handler (lambda (e) 'properly-handled!) thunk))))</font></div>

<div><font face="courier new, monospace"><br></font></div></blockquote><div>where proxy-exception-handler/catcher 1 & 2 are to represent an arbitrary chain of exception handlers that logics code may come up with. The i<span style="font-family:arial,helvetica,sans-serif">ntended behavior is</span></div>

<blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><font face="courier new, monospace"><br></font></div><div><font face="courier new, monospace">(parent-exception-handler (proxy-exception-handler/catcher1 </font><span style="font-family:'courier new',monospace">(proxy-exception-handler/catcher2 logics</span><span style="font-family:'courier new',monospace">))) => 'properly-handled!</span></div>

<div><span style="font-family:'courier new',monospace"><br></span></div><div><font face="courier new, monospace">(parent-exception-handler (proxy-exception-handler/catcher1 </font><span style="font-family:'courier new',monospace">logics</span><span style="font-family:'courier new',monospace">)) => 'properly-handled!</span></div>

<div><span style="font-family:'courier new',monospace"><br></span></div><div><font face="courier new, monospace">(parent-exception-handler </font><span style="font-family:'courier new',monospace">(proxy-exception-handler/catcher2 logics</span><span style="font-family:'courier new',monospace">)) => 'properly-handled!</span></div>

</blockquote></div><div><br></div><div><br></div><div>Actually evaluating these three tests showed:</div><div><br></div><div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><font face="courier new, monospace">(parent-exception-handler (proxy-exception-handler/catcher1 </font><span style="font-family:'courier new',monospace">(proxy-exception-handler/catcher2 logics</span><span style="font-family:'courier new',monospace">))) => </span><span style="font-family:arial,helvetica,sans-serif">infinite loop (!)</span></div>

<div><span style="font-family:'courier new',monospace"><br></span></div><div><font face="courier new, monospace">(parent-exception-handler (proxy-exception-handler/catcher1 </font><span style="font-family:'courier new',monospace">logics</span><span style="font-family:'courier new',monospace">)) => </span><font face="arial, helvetica, sans-serif">infinite loop (!)</font></div>

<div><span style="font-family:'courier new',monospace"><br></span></div><div><font face="courier new, monospace">(parent-exception-handler </font><span style="font-family:'courier new',monospace">(proxy-exception-handler/catcher2 logics</span><span style="font-family:'courier new',monospace">)) => 'properly-handled!</span></div>

</div></blockquote></div><div><br></div><div>To start with, great that we see that with-exception-catcher delivers out of the box for this usecase!</div><div><br></div><div>Thus we have <font face="courier new, monospace">with-exception-handler</font> left. I guess the best way would be if with-exception-handler inherently somehow would deliver for this, so that support for this kind of use would be transparent and not require possible updates of user code (e.g. any typical user code such as a PI calculator etc. could without needing code review just be run within a web server that uses this special IO error handling).</div>

<div><br></div><div>Is there any way to make <span style="font-family:'courier new',monospace">with-exception-handler</span> deliver for this usecase?</div><div><br></div><div><br></div><div><br></div><div><br></div>

<div><br></div><div><br></div><div>Last, what about that for introducing a port specific flag there would be the issue that the semantics of an IO error is vague -</div><div><br></div><div>Maybe you see something here I didn't get. As IO error for a port would count any error reported from the OS about the port, as well as timeouts within Gambit's IO system.</div>

<div><br></div><div>So this would correspond to any OS IO primitive invocation that gives an error return value (other than one that asks for a reiteration of the procedure, which some of them come with).</div><div><br></div>

<div>Another way to relate to it would be that such a port specific flag would serve to protect from requirement of programmer or admin intervention for any IO error that could possibly come up regarding the addressed ports.</div>

<div><br></div><div>What do you see here?</div><div><br></div><div><br></div><div><br></div><div>Best regards,</div><div>Mikael</div><div><br></div><div><br></div>