Kevin Finn <[EMAIL PROTECTED]> writes:

> Would it be reasonable to make this error a run-time crash or a
> popup warning?  I'm not sure how you would return an error from a
> bad option lookup, since there could be many different types of
> options and what might be an error condition from one would be a
> valid return value from another (-1 would be a good error value for
> a boolean, but not for a numeric range option, etc.).

Handling error conditions is a PITA if you want to write in a more
functional style.  One way to handle it is to make it so that #f as a
return value is always an error, and if there's a real value, then you
return something like (cons #t value).  This, of course, makes things
less elegant because you have to store the result before testing it.
I.e. you have to say:

  (let ((result (foo)))
    (if result
        (do-something (cadr result))))

but this does work around the #f "shadowing problem".  With this
approach, #f only means error.  Also, once we have a functioning
version of the and-let srfi, much of this gets easier.  You can write
an "and" that stores the value:

  (and-let ((result (foo)) (do-something (cadr result))))

and do-something will be called iff (foo) returns a non #f value, and
result will be bound to that value.  I think this is a really helpful
addition to the language.

Unfortunately, although working guile code is available for this srfi
(it was posted to the guile list a while ago), there's no copyright
for the code, and I haven't had time to track down the author(s), and
get that straightened out, or re-write it myself.  This has been
complicated by the fact that the guile list uses RBL and my mail
server's blacklisted right now :<

In code I've been writing recently (the text format parser), I've
actually been using a modified version of this convention.  A return
value is always a cons, and the "car" indicates success, so on success
you get (cons #t value ...) and on error you get (cons #f
error-message).  This is ugly, but with and-let, it gets a lot
cleaner...

Other ways I've been thinking of to handle the error propagation issue
are

  1) Use exceptions.  This is nice because it keeps the error handling
     code from mucking up your normal flow of control, but it's
     potentially hard to understand if you get the "catchers" too far
     away from the "throwers".

  2) Use multiple value returns - you could have the function return
     two return values (using (values x y ...)) where the first is
     always the status.  This is only marginally different from the
     first strategy I mentioned above, and it doesn't play nice with
     and-let, which seem like a great new syntax.

  3) Have a mutable "status" object that gets passed in.  If there's
     an error, modify it to reflect what's wrong.  This is often just
     plain ugly, but sometimes I've found it useful.

Anyway.  Just some thoughts.  If anyone has better ideas, I'd be happy
to hear them.

The reason I've got all this on the top of my head right now is
because in working on the text file format parser, I've had to deal
extensively with errors, so I've been thinking about it a lot.

Also, for anyone writing code that interacts with "unpredictable
sources" like an input file, or a socket, etc.  Please consider being
careful to catch all exceptions.  In some cases, errors may be serious
enough that everything should fall over, but in most cases, like when
parsing an input file, you want to make sure nothing can blow you up.

In the input parser, for example, I parse the entire file into an
intermediate data structure, run some tests to make sure everything is
OK and that the semantics of the data are correct AFAICT.  All of this
is done under the protection of false-if-exception in cases where I
can't check all the args.  Then, if everything checks out, I fire up
the engine and cram all the data in...

FWIW

-- 
Rob Browning <[EMAIL PROTECTED]> PGP=E80E0D04F521A094 532B97F5D64E3930

--
Gnucash Developer's List
To unsubscribe send empty email to: [EMAIL PROTECTED]


Reply via email to