Live data from Hacker News

On Error Handling in Rust

lucumr.pocoo.org

21–30 of 82 posts

Re: On Error Handling in Rust

#21
This is a sugar-coated version of errors as return values. It fixes the most glaring problem, which is code that does not check for errors, common in C:

     FILE* f = fopen("somefile", "r");
     fwrite("aha", 4, 1, f); // 
In Rust (pardon my rust, I'm totally ignorant), it'd be:

    let f = fopen("somefile", "r");
    fwrite("aha", f)?;
The compiler would know that fopen may return an error, and forbid me from running unchecked code. Nice!

I'd miss, however, the ability to handle all errors occurring from a segment of code in the same place, stuff that exceptions allow for. Pythonish example

    try: 
        db = pgsql.connect(localhost)
        stmt = db.prepare('INSERT INTO log VALUES(?,?)')
        stmt.execute(('debug', 'Note to self: debug logs are noncritical'))
    except Exception,e:
        console.write('Could not write log to database %s' % (str(e)))
Sometimes error recovery is the same for all of the segment. I realize one could extract a function for the commonly recovered code, but this may lead to a too-many-small-functions-with-one-caller(tm) smell.

Exceptions aren't the only way to achieve this. If Rust wants to keep return values as the error mechanism, perhaps it could find a way of allowing recovery to happen in the same place for a segment of code.

Re: On Error Handling in Rust

#22

This is a sugar-coated version of errors as return values. It fixes the most glaring problem, which is code that does not check for errors, common in C: FILE* f = fopen("somefile", "r"); fwrite("aha", 4, 1, f); // In Rust (pardon my rust, I'm totally ignorant), it'd be: let f = fopen("somefile", "r"); fwrite("aha", f)?; The compiler would know that fopen may return an error, and forbid me from running unchecked code.…

Maybe I am missing some subtleity here, but isn't the whole point of the described proposed feature that you would be able to replicate the Python code pretty much exactly?

  fn read_database() -> Result {
    let db = pgsql.connect(localhost)?
    let stmt = db.prepare("INSERT INTO log VALUES(?,?)")?
    stmt.execute(("debug", "Note to self: debug logs are noncritical"))?
  }
So to have the handling code there as well, wrap it in an outer function (I have no idea if this is anywhere close to actual Rust):

  fn read_database() {
    fn reader() -> Result
      let db = pgsql.connect(localhost)?
      let stmt = db.prepare("INSERT INTO log VALUES(?,?)")?
      stmt.execute(("debug", "Note to self: debug logs are noncritical"))?
    }
    match reader() {
      Document(d) => d,
      DatabaseError(err) => println!("Could not write log to database {}", err)
    }
  }

Re: On Error Handling in Rust

#23

This is a sugar-coated version of errors as return values. It fixes the most glaring problem, which is code that does not check for errors, common in C: FILE* f = fopen("somefile", "r"); fwrite("aha", 4, 1, f); // In Rust (pardon my rust, I'm totally ignorant), it'd be: let f = fopen("somefile", "r"); fwrite("aha", f)?; The compiler would know that fopen may return an error, and forbid me from running unchecked code.…

I think it could be done with a macro that takes a block as its argument.

Re: On Error Handling in Rust

#24
post #22

This is a sugar-coated version of errors as return values. It fixes the most glaring problem, which is code that does not check for errors, common in C: FILE* f = fopen("somefile", "r"); fwrite("aha", 4, 1, f); // In Rust (pardon my rust, I'm totally ignorant), it'd be: let f = fopen("somefile", "r"); fwrite("aha", f)?; The compiler would know that fopen may return an error, and forbid me from running unchecked code.…

Maybe I am missing some subtleity here, but isn't the whole point of the described proposed feature that you would be able to replicate the Python code pretty much exactly? fn read_database() -> Result { let db = pgsql.connect(localhost)? let stmt = db.prepare("INSERT INTO log VALUES(?,?)")? stmt.execute(("debug", "Note to self: debug logs are noncritical"))? } So to have the handling code there as well, wrap it in a…

Note my mention of the too-many-small-functions-with-one-caller(tm) smell. It refers to this solution.

Re: On Error Handling in Rust

#25
I' m someone who hasn't tried rust, yet. Is FromError the same like inner exceptions in C#? I'd like to dive into rust once, but somehow I do not see the elegance in the code shown.

I mostly do not care about the type of error condition and handle the error somewhere really far up the stack (log or messagebox) and provide the ability for a retry. Can i do something like a general try/catch far up the stack? in my opinion, this neatly prevents code from beeing littered with error handling which i very much prefer.

Re: On Error Handling in Rust

#27

This is a sugar-coated version of errors as return values. It fixes the most glaring problem, which is code that does not check for errors, common in C: FILE* f = fopen("somefile", "r"); fwrite("aha", 4, 1, f); // In Rust (pardon my rust, I'm totally ignorant), it'd be: let f = fopen("somefile", "r"); fwrite("aha", f)?; The compiler would know that fopen may return an error, and forbid me from running unchecked code.…

> This is a sugar-coated version of errors as return values.

By which you mean that errors as return values are bad, and that they are trying to sugar-coat the fact that they are using errors as return values?

Re: On Error Handling in Rust

#28

This is a sugar-coated version of errors as return values. It fixes the most glaring problem, which is code that does not check for errors, common in C: FILE* f = fopen("somefile", "r"); fwrite("aha", 4, 1, f); // In Rust (pardon my rust, I'm totally ignorant), it'd be: let f = fopen("somefile", "r"); fwrite("aha", f)?; The compiler would know that fopen may return an error, and forbid me from running unchecked code.…

Unlike some languages, function return values aren't special, they're just normal values, so you can handle the error locally like

  match fwrite("aha", f) {
      Err(e) => println!("Could not write log to database {}", e),
      Ok(_) => { /* no problem */ }
  }

Re: On Error Handling in Rust

#29
post #28

This is a sugar-coated version of errors as return values. It fixes the most glaring problem, which is code that does not check for errors, common in C: FILE* f = fopen("somefile", "r"); fwrite("aha", 4, 1, f); // In Rust (pardon my rust, I'm totally ignorant), it'd be: let f = fopen("somefile", "r"); fwrite("aha", f)?; The compiler would know that fopen may return an error, and forbid me from running unchecked code.…

Unlike some languages, function return values aren't special, they're just normal values, so you can handle the error locally like match fwrite("aha", f) { Err(e) => println!("Could not write log to database {}", e), Ok(_) => { /* no problem */ } }

Yeah, but that doesn't extend to

    match { let f = fopen(); fwrite("aha", f); fclose(f); } {
        Err(e) => println("either of fopen, fwrite or fclose failed"),
        _ => ()
    }
without something like a try! variant that breaks out of a block instead of returning from a function on error.

Re: On Error Handling in Rust

#30
post #28

Earlier quoted context omitted.

Unlike some languages, function return values aren't special, they're just normal values, so you can handle the error locally like match fwrite("aha", f) { Err(e) => println!("Could not write log to database {}", e), Ok(_) => { /* no problem */ } }

Yeah, but that doesn't extend to match { let f = fopen(); fwrite("aha", f); fclose(f); } { Err(e) => println("either of fopen, fwrite or fclose failed"), _ => () } without something like a try! variant that breaks out of a block instead of returning from a function on error.

This is exactly what the Error / Either monad does.
Post reply on HN