On 04/25/2013 07:18 AM, Gábor Lehel wrote:
You write:

> So what actually happens if `new` encounters an error? To understand
> that it's important to know that what `new` returns is not a `File`
> but an `Option<File>`. If the file does not open, and the condition
> is handled, then `new` will simply return `None`. Because there is an
> implementation of `Writer` (the trait required ultimately required for
> types to implement `write_line`) there is no need to inspect or unwrap
> the `Option<File>` and we simply call `write_line` on it. If `new`
> returned a `None` then the followup call to `write_line` will also
> raise an error.

I'm an outsider, so apologies if I'm off the right track. But this sounds wrong to me. Isn't the point of condition handlers to /handle the condition/? Meaning resolve the problem, so that processing can continue? Here as far as I can tell, they're only being used to say "fail differently", which then leads to failing again the next time you try to do something. Opening a file was actually one of the examples used to illustrate the condition system way back when[1].


That's right. This isn't using conditions the way they are typically described.

> * XXX: How should we use condition handlers that return values?

IMHO the right way would be to provide more fine-grained information about the error (perhaps raising different conditions depending on the error, instead of always the same condition and a giant enum describing it), and use the return value of the condition to set policy wrt how to handle it and/or to provide a substitute (as in the example). If there's nothing reasonable that could be done, don't raise a condition, fail unconditionally.

That is how you would expect a condition system to work, I agree. It has been argued to me that failing unconditionally is not acceptable because the recovery strategy requires creating new tasks, which is much more expensive than unwinding a few frames of stack.


Whether to respond to failure by failing the task or by indicating it in the return value seems like it would be better handled by having separate functions for each. In the case where you expect success, the result shouldn't be an Option. If the result is an Option, it shouldn't fail the task (whether or not a condition handler is present). So for example:

open<P: PathLike>(path: &P, mode: FileMode, access: FileAccess) -> FileStream

try_open<P: PathLike>(path: &P, mode: FileMode, access: FileAccess) -> Option<FileStream>

If the expect-success version of a function returns (), the try_ version would return bool rather than Option<()> (which are isomorphic).

Upon encountering an error, open() would raise a condition, and then continue if possible, otherwise fail!().

I'm not sure whether try_open() would raise a condition or not. The way conditions were described, if they aren't handled, the task fails. try_open() definitely shouldn't fail. Would it be reasonable to raise a condition and instead of failing, return None if it's not handled? If not, then try_open() shouldn't raise any conditions, and should just return None.

The obvious drawback is twice as many functions, but it feels preferable to forcing two different behaviours onto the same function. The fast (expect-success) path would be just as clean as before, if not cleaner.

[1] https://mail.mozilla.org/pipermail/rust-dev/2012-October/002545.html

With this strategy could we make the `try_` return values return `Result<FileStream, SomeErrorType>` (not using conditions at all)? Then nil-returning functions would need to be `Option<SomeErrorType>`. Having two ways to perform every I/O operation will 'infect' all code that uses I/O indirectly. For instance, we have a `ReaderUtil` trait that defines maybe two dozen methods. Do those all get duplicated? That seems pretty disastrous to me.

You mentioned disliking the giant IoError enum, and I agree, but I don't know a better way to represent it. We don't have subclassing to create an Exception type hierarchy. Do you have any suggestions?

-Brian

_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to