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