Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Isn't that only necessary because rust doesn't have exceptions ?


? isn't necessary, it's just nice to have.

Rust doesn't want to have exceptions; it prefers return value based error handling ("monadic error handling", specifically). A lot of people seem to be under the impression that Rust's error handling model is a way of emulating exceptions -- it's not; it's a different model, and we don't want to emulate exceptions. The fact that error propagation is a common task doesn't mean that Rust's way of providing it is done to emulate exceptions.

------

In a sense, every part of Rust's error handling model is "necessary because Rust doesn't have exceptions". Similarly, every part of Java's error handling model is "necessary because Java makes it hard to do monadic error handling". Saying "X is only necessary because you don't have Y" when X is an alternative to Y isn't a very useful statement.


You are just answering to the style of my question, while you perfectly understood the meaning and avoided to provide the answer.

Basically this feature is here to provide an easy propagation of errors, something an exception system does for you for free.

"?" exist because the current error handling make it inconvenient to propagate errors, and is a workaround to make it less of a pain.

It's alright. There is no shame in it. Just say so, don't try to talk your way out of it.


> something an exception system does for you for free.

That's the point, it doesn't, you pay for the exception system and the implicitness that comes with it. Your comment portrays exceptions as the default that monadic errors are playing catch-up with. I could easily do the reverse.

> is a workaround to make it less of a pain.

You say workaround, I say feature.

Ultimately, monadic errors and exceptions have tradeoffs.

Like I said, given any tradeoff between feature A and feature B, you can always say "subfeature X of A exists because we don't have B". It's not a meaningful thing to say.

I didn't avoid an answer, I genuinely think that your comment has no substance to it because it pretends that exceptions are a "default" system.


I consider "not having exceptions" to be a feature that the ? operator helps to enable. Go also doesn't have exceptions, but they don't have the ? operator, which I find to be a little repetitive while coding. My fingers are outrageously good at:

if err != nil { return err }

Comparing Rust to a language with exceptions, like Java, the only difference is that they places that the code can return is explicit rather than implicit, because of that one extra character. I find this extremely pragmatic since most of the time errors just need to be propagated up to a place where they can be handled, but you still need to know when that may happen.


But technically you're doing this wrong, since you should be gift-wrapping your errors in Go. So either you have to be a human exception handler, or god help you should you need to figure out where an error actually occurred.


In some sense, yes. But in another sense, not everyone agrees that exceptions are a good idea, and so would prefer this even if we did.


It's all the same stuff, man. Rust just:

* makes you be explicit about call sites which throw

* makes it easy to reify fallible computation (so it can be stored in e.g. a Future)

For instance:

    fn foo() -> Result<Value, IoError> {
      let x = a()?;
      let _ = b();
      if someCondition {
        return Err(IoError::Whatever)
      }
      return c(x).unwrap();
    }

is just

    Value foo() throws IOException {
      x = a();
      try {
        b();
      } catch(Exception e) { /* TODO: ERROR HANDLING? */ }
      if (someCondition) {
        throw new IOException();
      }
      try {
        return c(x);
      } catch(Exception e) { abort(); }
    }
This is made especially clear by Swift's model which is pretty much exactly the same as Rust's, but makes it look like exceptions:

    // RIP typed errors
    func foo() -> Value throws {
      let x = try a() // "rethrow"
      try? b()
      if someCondition {
        throw "Oh No IO!"
      }
      return try! c(x)
    }


It is the same stuff, exactly why errors should be values with some sugar for using them instead of a crazy parallel universe. :-)


You're forgetting about language pads and shenanigans.


Unwinding is an implementation of exceptions. You can implement them as returns, or, in the case of Swift, passing in a pointer for the Error type.


Okay that's fair. I usually equate them because every language I've ever used has implemented them with unwinding.


... landing pads. not language pads. Sheesh!


You should add language pads to your sick sleeve. Never4get.


Your Rust code has a compiler warning - you've ignored the result of b() which is returning a Result which must be handled.


No, `let _ = x` is the official way to ignore a value explicitly. The lint ignores it.

(My code does have an error because I forgot to wrap the result in Ok)


No, this is a standard operator found in many programming languages, including ones with exceptions:

https://en.wikipedia.org/wiki/Safe_navigation_operator




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: