|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [MirageOS-devel] Error handling in Mirage - request for comments!
>
> I've had a go at writing this proposal up ("system 5"):
>
> https://github.com/talex5/mirage-www/blob/errors/tmpl/wiki/error-handling.md
>
> I think someone who wants to advocate this style should check it /
> change it. It probably needs some worked examples showing it being
> used too.
>
The interface given for "system 5" is not comparable for the one given
for "system 4", giving a false sense of verbosity to the "system 5"
example. The equivalent to the "system 4" example, would just be:
type error
val pp_error : formatter -> error -> string
val read :
t -> int64 -> page_aligned_buffer list ->
(int, error) result
Constructors of `error` should only be exposed if they are intended to
be matched on. So if `read` has a kind of error ``Foo` which was
intended to be matched on then the "system 5" approach would be:
type error = private [> `Foo]
val pp_error : formatter -> error -> string
val read :
t -> int64 -> page_aligned_buffer list ->
(int, error) result
whilst "system 4" would probably look like:
exception Foo
val read :
t -> int64 -> page_aligned_buffer list -> int
The splitting of `error` up into `write_error` and `read_error` is only
needed if you have an interface with different sets of matchable
errors. So if you had a `read` function with a matchable error ``Foo`
and a `write` function with matchable error ``Bar`, then you would get
the following:
type read_error = private [> `Foo]
type write_error = private [> `Bar]
type error
val pp_error : formatter -> error -> string
val write_error : write_error -> error
val read_error : read_error -> error
val read :
t -> int64 -> page_aligned_buffer list ->
(int, read_error) result
val write :
t -> int64 -> page_aligned_buffer list ->
(int, write_error) result
whilst "system 4" would probably look like:
exception Foo
exception Bar
val read :
t -> int64 -> page_aligned_buffer list -> int
val write :
t -> int64 -> page_aligned_buffer list -> int
A key benefit of "system 5" is that the signature contains all the
interesting information about `read` and `write`. It clearly states that
they are expected to fail sometimes, and that the only errors on which it is
reasonable to behave specially are a `Foo` returned by `read` or a `Bar`
returned by `write`. `System 4` does not convey any of this information.
>> Some nice combinators should be provided for using ('a, 'b) Result.t and
>> ('a, 'b) Result.t Lwt. and for lifting an ('a, Foo.error) Result.t into
>> an ('a, Bar.error) Result.t.
>>
>> Exceptions that escape their intended scope, should always be treated as
>> a programming error.
>
> Yes, by definition. But what should the "intended scope" be, and how
> do we ensure the producer and consumers of the exception agree?
Exceptions should basically never delibrately cross module
boundaries. They should certainly not be part of the exposed API of a
library. By "exceptions that escape their scope" I essentially meant
exceptions used in third-party APIs (e.g. Not_found produced by
List.find), these should always be caught as early as possible and
handled appropriately.
Occasionally it is reasonable for an exception like "Invalid_argument"
to be part of a library API, where the exception is not intended to be
caught but merely to indicate that there has been a programmer error.
It is also reasonable to use exceptions locally for control-flow, but
again these should not escape into the visible API.
Regards,
Leo
_______________________________________________
MirageOS-devel mailing list
MirageOS-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/mirageos-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |