Exception handling?

Jan Krynicky JKRY3025@comenius.ms.mff.cuni.cz
Wed, 11 Oct 1995 16:32:32 +0100


Peter Achten wrote:
> 
> On Fri, 6 Oct 1995 14:31:54 you wrote:
> 
> >Is there any serious reason for the absence of the exception=20
> >handling? Or just have not been enough time to add it?
> >
> >                                                        Jenda Krynicky
> 
> This depends in a sense on what you mean by _exception_. For instance, in
> the Clean File I/O system erroneous file operations do not raise an
> exception but rather yield a Boolean result stating whether an exception
> occurred. In the Clean Event I/O system exceptions related to 
> keyboard and mouse input are delegated to the event stream. So it 
> depends on the kind of exception you would like to handle. Could 
> you give some suggestions? 
> 
> Cheers, Peter.
> 
I mean something like "exceptions" in Standadr ML,
something more than abort "...". If I (the function) am failing
that doesn't meen that everything is lost.

I would rather write :
    (x/y handle Zero -> 0)
then
    if (y==0) 0 (x/y)
if the expression would be more complex, it wouldn't be nice to check 
for every posible problem (division by zero,square root of negative 
num. etc.)

2)
product::[Real] -> Real
product [] = 1
product [0:tail] = 0
product [x:tail] = x*(product tail)

This is a pretty straight-forward definition, but if the list 
contains 0, it does all unnecessary multiplications the way back.

supose this version:

exn Product
product list = evalproduct list 
                 handle Product -> 0
   where              
     product [] = 1
     product [0:tail] = raise Product
     product [x:tail] = x*(product tail)
     
P.S.:Imagine that it is a tree and the operation is more complex.

with booleans:
product list = prod
  where
   (_,prod) = evalproduct list
   evalproduct [] = 1
   evalproduct [0:_] = (FALSE,0)
   evalproduct [x:list] = (TRUE,if nozero prod 0)
     where
      (nozero,prod) = evalproduct list
      
?What is clearer?

3)Supose I have a partial function f and would need a total 
function g, to be the same for the range of f and some acceptable 
value for other.

with exceptions:
g args = f args handle _ -> some_value

without them you must know all "bad" args and do the necessary 
checking.

4)The boolean result of file I/O system is usefull, but not very 
kind. I have to explicitly check all the bools, give them names, ...
It wouldn't be posible to use it as it goes (f (g (read f 10)) 
and then check all posible errors at once.
Especialy if I want to return the same value for every error!

5)The only information that this maintain is that it failed. 
I'd sometimes(!) need to get more info (type of error, etc.)
I could return more info, but it would mean that I'd have to define a 
type for it. (Using "numbers" of errors is not a solution, I'd need 
it parametrized.) So you create a type for reporting file errors.
It would pass enough info and everything will be O.K.
Until I'd need to add some new errors (bad_format,...).
My functions would need to report either Cleans file_errors and my 
aditional ones. To build a "tree" of error types:
::ImageReadError = BadFormat File                //reading images
                 |   ...
                 | Cleans_error FileError

::ObjImgError = AllreadyShown                    //graphical objects
              | OutOfScreen
              | ...
              | ImageReadError ImageReadError

is a good solution, but there can make problems multiple inheritance.
And more it would seem pretty terrible.

                                               Jenda 
                                               
P.S.:Supose the program is waiting for input, it can only wait. 
It could try to evaluate something in advance (Clean is lazy, so
it's not important when is the evaluation proceded.).
But it can't, an error (division by zero, ...) could ocure either if
the result woudn't be needed and not so diligent program would 
succeed. But the result of that expression could be exception, that 
is passed to superexpressions (up to the whole program) only when the 
value is needed (FALSE and EXN -> FALSE).{(not x==0) and (.../x)}  
=> you can't evaluate in advance because it could cause an 
unnecessary abort ("division by zero").
--------------------------------------------------------
Jan Krynicky
student of Faculty of Mathematics and Physics
Charles University
Prague