On Feb 19, 2014, at 3:40 PM, Jason Fager <jfa...@gmail.com> wrote:
> Can you point to any scripting langs whose lines equivalent just silently
> ignores errors? I'm not aware of any; even perl will at least populate $!.
>
No, because I typically don’t think about errors when writing quick scripts. If
the script blows up because I had a stdin error, that’s fine, it was never
meant to be robust.
I just commented on #12368 saying that now I’m leaning towards suggestion #2
(make .lines() fail on errors and provide an escape hatch to squelch them).
This will more closely match how scripting languages behave by default (where
an exception will kill the script).
> I opened https://github.com/mozilla/rust/issues/12130 a little while ago
> about if_ok!/try! not being usable from main and the limitations for simple
> use cases that can cause. Forgive a possibly dumb question, but is there a
> reason main has to return ()? Could Rust provide an 'ExitCode' trait that
> types could implement that would provide the exit code that the process would
> spit out if it were returned from main? IoResult's impl would just be `match
> self { Ok(_) => 0, Err(_) => 1 }` and your example would look like
>
> fn main() -> IoResult<~str> {
> for line in io::stdin().lines() {
> print!(“received: {}”, try!(line));
> }
> }
There is no precedent today for having a function whose return type must
conform to a trait, without making the function generic. Furthermore, a
function that is generic on return value picks its concrete return type by the
type constraints of its call site, rather than by the implementation of that
function. I also question whether this will work form an implementation
standpoint. Today the symbol for the main() function is predictable and is the
same for all main functions. With your suggested change, the symbol would
depend on the return type. I don’t know if this matters to rustc; the “start”
lang item function is passed a pointer to the main function, but I don’t know
how this pointer is created.
But beyond that, there’s still issues here. Unlike in C, a Rust program does
not terminate when control falls out of the main() function. It only terminates
when all tasks have ended. Terminating the program sooner than that requires
`unsafe { libc::abort() };`. Furthermore, the main() function has no return
value, and does not influence the exit code. That’s set by
`os::set_exit_status()`. If the return value of main() sets the error code that
will overwrite any error code that’s already been set.
Perhaps a better approach is to define a macro that calls a function that
returns an IoResult and sets the error code to 1 (and calls libc::abort()) in
the Err case, and does nothing in the Ok case. That would allow me to write
fn main() {
abort_on_err!(main_());
fn main_() -> IoResult<()> {
something_that_returns_io_result()
}
}
---
While writing the above code sample, I first tried actually writing the
read_line() loop, and it occurs to me that it’s more complicated than
necessary. This is due to the need for detecting EOF, which prevents using
try!(). We may actually need some other macro that converts EOF to None,
returns other errors, and Ok to Some. That makes things a bit simpler for
reading, as I can do something like
fn handle_stdin() -> IoResult<()> {
let mut r = BufferedReader::new(io::stdin());
loop {
let line = match check_eof!(r.read_line()) {
None => break,
Some(line) => line
};
handle_line(line);
}
}
Still not great, but at least this is better than
let line = match r.read_line() {
Ok(line) => line,
Err(IoError{ kind: EndOfFile, .. }) => break,
Err(e) => return Err(e)
};
-Kevin
_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev