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