[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [MirageOS-devel] Error handling in Mirage - request for comments!
On 11 February 2015 at 16:41, Leo White <lpw25@xxxxxxxxx> wrote: >> >> 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: Good point. I've updated the system 4 example to include the exception definitions: https://github.com/talex5/mirage-www/commit/97b149b9e04e9127920961d25f5082e36c124bc4 > 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. Yes, but the question is whether this information is worth the overhead. In particular: - We must assume that some implementation of a Mirage module type may produce an error (they're all about I/O, after all), so annotating every function to say this doesn't provide any extra information. - Knowing that e.g. `read` won't return `Is_read_only` is useful when doing exhaustive matching, but we can't do that anyway for generic module types. >>> 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. That's one approach, but others are possible (though I think everyone agrees that Not_found shouldn't be an exception). Personally, I'd say anything you wouldn't feel comfortable displaying to the user shouldn't be an exception. -- Dr Thomas Leonard http://0install.net/ GPG: 9242 9807 C985 3C07 44A6 8B9A AE07 8280 59A5 3CC1 GPG: DA98 25AE CAD0 8975 7CDA BD8E 0713 3F96 CA74 D8BA _______________________________________________ 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 |