Live data from Hacker News

Rust for C++ Programmers Part 7: Data Types

featherweightmusings.blogspot.com

21–30 of 39 posts

Re: Rust for C++ Programmers Part 7: Data Types

#21
post #20

Earlier quoted context omitted.

"only catch what you can handle" is incredible nonsense. Your code is the only code that knows how the code it's calling might fail -- it MUST catch all exceptions and either handle them, or re-raise them with a well defined type that is documented and declared in your API. Anything else just leads to buggy software that has a try/catch block at the top level of the event loop/main/thread start function to deal with…

Obviously you should be converting exceptions that leave your library into other areas, but internally? Converting exceptions over and over and over again just means losing information from those exceptions, or worse hiding them. If I'm forced to dump a stack-trace to the text file, I want the exact exception that caused the problem, not some vague "Operation Exception" that quintuply wraps my actual desired exceptio…

That doesn't make any sense. Defensive coding means not silently discarding errors (by returning null, in this case), and has nothing at all to do with exceptions.

As for rewrapping errors, yes, each subsystem should have its own error space. You don't lose data by nesting errors; on the contrary, each level can add additional context to an error result that makes debugging an unexpected issue far easier.

Re: Rust for C++ Programmers Part 7: Data Types

#22
post #14

Earlier quoted context omitted.

I tend to practice "only catch what you can handle" in exception-enabled languages - I haven't written in a systems language in almost a decade, mostly bad memories of C. How much does error-handling get in the way when you have to live without stack unwinding?

"only catch what you can handle" is incredible nonsense. Your code is the only code that knows how the code it's calling might fail -- it MUST catch all exceptions and either handle them, or re-raise them with a well defined type that is documented and declared in your API. Anything else just leads to buggy software that has a try/catch block at the top level of the event loop/main/thread start function to deal with…

Tell that to the Erlang guys, who have been writing some of the most fault-tolerant code of the past two decades with an explicit catch-what-you-can-handle attitude by design.

Their failure model lies in proper task supervision, coding for the expected case, and letting errors propagate up to the task level, where you can either kill a task, log and handle, propagate, or do whatever you wish.

Re: Rust for C++ Programmers Part 7: Data Types

#23
post #6
post #2

I'm curious why this isn't automatically destructured: struct IntPoint (int, int); fn foo(x: IntPoint) { let IntPoint(a, b) = x; // Note that we need the name of the tuple // struct to destructure.

What do you mean by "automatically destructured"? If you mean the extra step of destructuring in the function body, that's not necessary. You can destructure like that anywhere that a pattern is accepted, which includes function parameter lists: struct Foo(int, int); fn bar(Foo(a, b): Foo) { println!("a: {}, b: {}", a, b); } fn main() { let qux = Foo(1, 2); bar(qux); // a: 1, b: 2 }

What they mean is that there would be special cases for let patterns so that

     let (a, b) = Foo(a,b);
is a fine destructuring. It would be a special case for let, since the pattern would have to be more explicit in function arguments and in match, but I think they have a good point.

Re: Rust for C++ Programmers Part 7: Data Types

#24
post #11
post #5

I would love to see an article like this for error handling in Rust. I was really interested in using conditions, but those were apparently backed out. Which leaves error handling through return values and macros. This seems like a step back from Exceptions to me. I want to be convinced otherwise, but I'm struggling to see how this is better than other mechanisms.

> This seems like a step back from Exceptions to me. I > want to be convinced otherwise, but I'm struggling to > see how this is better than other mechanisms. In a low-level language, guaranteeing memory safety in the face of resumable exceptions would be a nightmare. See Graydon's original post on the choice to avoid exceptions: https://mail.mozilla.org/pipermail/rust-dev/2013-April/00381... Selected quote: > In par…

> resumable exceptions

The word resumable is important to that quote, which isn't arguing against exceptions in general.

Re: Rust for C++ Programmers Part 7: Data Types

#25
post #24
post #11

Earlier quoted context omitted.

> This seems like a step back from Exceptions to me. I > want to be convinced otherwise, but I'm struggling to > see how this is better than other mechanisms. In a low-level language, guaranteeing memory safety in the face of resumable exceptions would be a nightmare. See Graydon's original post on the choice to avoid exceptions: https://mail.mozilla.org/pipermail/rust-dev/2013-April/00381... Selected quote: > In par…

> resumable exceptions The word resumable is important to that quote, which isn't arguing against exceptions in general.

I suspect a similar analysis holds, though. After all, throw-catch style exceptions do involve resumption, just not at the point at which they're thrown. You have a similar challenge in making sure that you haven't left the world in an inconsistent state when an exception emerges from some code.

That said, i am skeptical that there is a significant safety practical difference between the use of checked exceptions, and the use of return values with a try! macro. In both cases, you are forced to acknowledge in the code that an exception can be thrown, which means that you have a chance to do the right thing about consistency.

We could imagine a version of checked exceptions where individual throw sites have to be tagged. A parallel universe version of Java [1] might look like:

  InputStream in = whatever();
  int b = in.read() throw IOException;
Wouldn't that be exactly isomorphic to Rust's use of try! ?

[1] No, not that Parallel Universe version of Java: http://blog.paralleluniverse.co/2014/05/01/modern-java/

Re: Rust for C++ Programmers Part 7: Data Types

#26

I just read the first section, just the section on structs -- what's different here, from C? It provides all of the same features, with a slightly different syntax.

Read the rest!

To start you off, the best and most major difference to C is that Rust structs can have destructors.

Re: Rust for C++ Programmers Part 7: Data Types

#27
post #14

Earlier quoted context omitted.

I tend to practice "only catch what you can handle" in exception-enabled languages - I haven't written in a systems language in almost a decade, mostly bad memories of C. How much does error-handling get in the way when you have to live without stack unwinding?

"only catch what you can handle" is incredible nonsense. Your code is the only code that knows how the code it's calling might fail -- it MUST catch all exceptions and either handle them, or re-raise them with a well defined type that is documented and declared in your API. Anything else just leads to buggy software that has a try/catch block at the top level of the event loop/main/thread start function to deal with…

Java's checked exceptions are the worst — a failed language experiment if there ever was one.

Thank Guava for Throwables.propagate().

Re: Rust for C++ Programmers Part 7: Data Types

#28

Earlier quoted context omitted.

"only catch what you can handle" is incredible nonsense. Your code is the only code that knows how the code it's calling might fail -- it MUST catch all exceptions and either handle them, or re-raise them with a well defined type that is documented and declared in your API. Anything else just leads to buggy software that has a try/catch block at the top level of the event loop/main/thread start function to deal with…

Tell that to the Erlang guys, who have been writing some of the most fault-tolerant code of the past two decades with an explicit catch-what-you-can-handle attitude by design. Their failure model lies in proper task supervision, coding for the expected case, and letting errors propagate up to the task level, where you can either kill a task, log and handle, propagate, or do whatever you wish.

No, Erlang has been writing fault-tolerant code with an explicit functional, immutable design, with very explicit semantics for defining process supervision and restart at every point in the heirarchy.

That's not "catch-what-you-can-handle", that's "use functional programming and pervasive consideration of fault handling to ensure that you can handle faults at any layer".

Re: Rust for C++ Programmers Part 7: Data Types

#29
post #27

Earlier quoted context omitted.

"only catch what you can handle" is incredible nonsense. Your code is the only code that knows how the code it's calling might fail -- it MUST catch all exceptions and either handle them, or re-raise them with a well defined type that is documented and declared in your API. Anything else just leads to buggy software that has a try/catch block at the top level of the event loop/main/thread start function to deal with…

Java's checked exceptions are the worst — a failed language experiment if there ever was one. Thank Guava for Throwables.propagate().

The only failed language experiment are exceptions themselves.

I don't use Java APIs that don't throw checked exceptions; if your code does that, I won't even consider working at your place of business, because that means you don't understand that you've written a massive pile of ill-defined failure-prone code.

Unchecked exceptions are GOTO on steroids, and those GOTOs are part of the API contract. Java makes exception handling explicit and compiler checked -- hacking around checked exceptions makes exception handling implicit and human-checked, meaning that there's absolutely no static verification of a critical component of your API contract.

The problem isn't checked exceptions, the problem is that exceptions suck, and the only way to use them in a way that doesn't expose your code base to implicit GOTO failure modes is to use checked exceptions.

On our production software, we don't use exceptions at all, except where required by an API; instead, we always use monadic error handling. We have an uncaught exception handler for threads/thread pools/etc that does one thing: log the exception, and terminate the running Java process via System.exit(), allowing the process's watchdog to restart the failed process.

By its very nature, an uncaught exception is unexpected and places the process in an unknown state; the only safe thing to do is exit. Since the throwing of an uncaught exception triggers full process failure, it very much encourages defensive, safe practices that ensure that all error cases are handled and compiler-checked.

The result: our code is far more stable and reliable than any other project I've worked on, especially projects that have made use of runtime exceptions.

Re: Rust for C++ Programmers Part 7: Data Types

#30
post #27

Earlier quoted context omitted.

Java's checked exceptions are the worst — a failed language experiment if there ever was one. Thank Guava for Throwables.propagate().

The only failed language experiment are exceptions themselves. I don't use Java APIs that don't throw checked exceptions; if your code does that, I won't even consider working at your place of business, because that means you don't understand that you've written a massive pile of ill-defined failure-prone code. Unchecked exceptions are GOTO on steroids, and those GOTOs are part of the API contract . Java makes except…

I won't even consider working at your place of business...

Praise be! The feeling is mutual. I agree to disagree.

Post reply on HN