News for hackers. Stuff that matters.
Re:Rust vs. Go in 2023 by threeseed on Sunday August 13, 2023 @04:26AM (#37107818)
> Go is more verbose than Java

In real world use ridiculously so.

The lack of exceptions, Option type or ability to chain or manipulate errors means every line ends up wrapped in a 90s style "if error" check. Which ends up making code less robust than languages with more modern approaches like Rust, Scala, Swift etc.

Re:Rust vs. Go in 2023 by xyproto on Sunday August 13, 2023 @04:34AM (#37107866)
You can look at "if err == nil" and tell what is going on, but who knows which layer of exception handling will catch that "throws".
Re:Rust vs. Go in 2023 by threeseed on Sunday August 13, 2023 @04:37AM (#37107881)
In JVM languages it is easy to know what is catching what.

The method type signatures clearly specify what exceptions will be thrown.

And the compiler requires you to deliberately handle those exceptions.

But I wouldn't consider Java to be the best approach for error handling anyway.

Re:Rust vs. Go in 2023 by kaba0 on Sunday August 13, 2023 @04:47AM (#37107936)
Which is the only sane thing in most cases. What can you do inside the helper function of a helper function with an incorrect user data? The only sane place to handle it is n levels up, so bubbling up is the correct default. At least rust has a handy macro for it, but go’s error handling is catastrophic, not a proper sum type, nor some form of propagation… it is literally the bad errno from C burned into the language.
Re:Rust vs. Go in 2023 by Aditya_Garg on Sunday August 13, 2023 @12:41PM (#37111551)
In go, you should manually propagate the errors up by returning them. At the n levels up, you handle the error. It's a bit cumbersome during write time but a life saver during read/debug time.
Re:Rust vs. Go in 2023 by kaba0 on Sunday August 13, 2023 @01:30PM (#37112049)
So manually obscuring the control flow/business logic with boilerplate bubbling up is more readable at debug/read time than it being implicitly, trivially there?
Re:Rust vs. Go in 2023 by memefrog on Sunday August 13, 2023 @05:07AM (#37108065)
>90s style "if error" check

What makes it '90s style' other than you don't like it?

Calling something "90s style" and its alternative "modern" is a thought-terminating cliche.

Re:Rust vs. Go in 2023 by kaba0 on Sunday August 13, 2023 @05:51AM (#37108320)
There have been many discussions on the topic of go’s error handling, the main gripes of people can be summarized as:

- it returns both a return value and the error value, not xor. The convention is to use the error value only if returned, but sometimes the other “slot” is also used. If you squint a bit, this is exactly what errno does in C. The better, ML-y or exception-y way gives you a sum type instead, which can’t be mishandled.

- you have to handle it in-place with no convenient shorthand allowing for handling it at another layer (and usually that’s the only meaningful way forward). Also, error handling is a cross-cutting concern, squeezing it inside your business logic is (in my opinion) a bad thing.

Re:Rust vs. Go in 2023 by memefrog on Sunday August 13, 2023 @08:04AM (#37109116)
It's not what errno does in C. errno in C is a thread-local variable which means accessing it is inefficient (it uses thread-local storage, which is much more expensive than a local variable) and you have to do awful things like save errno at the beginning of signal handlers if you call a function in the signal handler that can set errno (basically: any library function).

Whether or not it's better to have a sum type (IMO it isn't), what Go has isn't anything like errno. errno is an ugly wart on the POSIX interface, which is otherwise quite nice. For example, Linux system calls directly return negative error codes, which is a much better way of handling errors, and then the libc has to set errno and return -1. Awful.

>- you have to handle it in-place with no convenient shorthand allowing for handling it at another layer (and usually that’s the only meaningful way forward). Also, error handling is a cross-cutting concern, squeezing it inside your business logic is (in my opinion) a bad thing.

That you say this and then advocate for optional<T>/result<t,e> is insane. That's exactly what a sum type does: it squeezes error handling into your business logic. And no, papering over that with ugly ? operators everywhere is not a solution, it is syntactic sugar. Error handling is part of the logic of your program. It is not just some 'ah we'll return it' thing. Many operations can fail and many errors are recoverable.

Re:Rust vs. Go in 2023 by kaba0 on Sunday August 13, 2023 @08:55AM (#37109549)
> errno in C is a thread-local variable which means accessing it is inefficient

Which is an implementation detail, has nothing to with its semantics what we discuss here. Certain C compilers do wild things with errno as well.

I’m not advocating for optional/result types, I personally believe that checked exceptions are the ideal solution, but it is a thoroughly underutilized tool in PL designs (Java has it, though it has many warts, but that is not inherent to the concept). Hopefully with the wake of effect-typed languages it could change.

With that said, in Rust’s low-level case it makes sense to avoid exceptions, and sum types are an okay solution, especially if it has a handful macro for bubbling up. What go has is just straight up wrong.

Re:Rust vs. Go in 2023 by ssokolow on Monday August 14, 2023 @02:55PM (#37125163)
Java's ecosystem is moving away from checked exceptions because their "bolted onto the return type as a sidecar" design doesn't compose well with functional-style APIs.

Monadic error handling (Rust's Option<T>/Result<T, E>) avoids that issue by putting the error inside the return type as a normal value.

(Which is why, on multiple occasions, I've seen people call Result<T, E> "checked exceptions done right/properly".)

Re:Rust vs. Go in 2023 by kaba0 on Monday August 14, 2023 @03:53PM (#37125990)
> checked exceptions done right/properly

But they fail at including a stacktrace, autobubbling up, auto-unwrap and customizable "hit radius" with a try-catch block (okay, I'm sure some Monadic construct allows for that, but e.g. Rust's version does not).

Re:Rust vs. Go in 2023 by steveklabnik on Monday August 14, 2023 @04:17PM (#37126254)
Try blocks exist in Rust nightly, but given that an IIFE closure gives nearly the same results, there hasn't been a ton of pressure to stabilize them. I wish the team would though.
Re:Rust vs. Go in 2023 by ssokolow on Monday August 14, 2023 @06:49PM (#37127762)
1. Remember that Rust takes a Minimum Viable Product approach to 1.0 releases. There are experiments in adding stack traces in third-party error-handling crates that could eventually lead to additions to the standard library, but we've already gone through at least three iterations (error-chain, failure, anyhow, and possibly eyre) and already have two deprecated methods forever stuck on the standard library Error trait, so they're taking it slowly.

(Plus, true exception handling is messy for a language that cares so much about FFI. Look at the discussions surrounding how panic! unwinding should behave at FFI boundaries.)

2. I think completely automatic bubbling would be a misfeature, and the `?` operator is a good balance between concise ease-of-use and the Rust focus on "code is read far more often than it's written".

3. Again, the `?` operator. I think completely automatic unwrap would also be a massive footgun and comprehension hazard.

4. As mentioned in the other reply, try blocks are in development. (See my previous comment about Rust adopting a Minimum Viable Product approach to v1.0)

https://caniuse.rs/ is a great illustration of how far we've already come and how minimal Rust 1.0 was.

Re:Rust vs. Go in 2023 by erik_seaberg on Sunday August 13, 2023 @05:57AM (#37108361)
That's when automated error handling began to be widely supported in early versions of mainstream languages: C++ (1985), Perl (1987), Python (1991), Java (1995). As time passes, I think it's healthy for us to expect new languages to learn from history and launch with more complete feature sets.
Re:Rust vs. Go in 2023 by memefrog on Sunday August 13, 2023 @07:55AM (#37109049)
'Automated error handling' is a misfeature in a language where correctness matters. Perl and Python can use exceptions and there it makes sense. It makes no sense for a language without garbage collection and frankly the only system where it actually works well is Common Lisp, which has restarts. Without restarts, exceptions are just error codes but with spooky action at a distance.
Re:Rust vs. Go in 2023 by kaba0 on Sunday August 13, 2023 @08:48AM (#37109479)
What does having/not-having a GC have to do with correctness?
Re:Rust vs. Go in 2023 by ssokolow on Monday August 14, 2023 @02:48PM (#37125031)
It's been said many times that Go feels like a language written by people who stopped paying attention to programming language research after the 1990s, as well as that it was written by people who look at C and think the only things that are less than perfect about it in the modern world are memory-safety and lack of a first-class concurrency story.

Some examples (not an exhaustive list):

1. Fibers/stackful coroutines (See "Fibers under the magnifying glass" by Gor Nishanov for why they were hugely popular in the 90s and then got abandoned by all the major OSes and programming languages → http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2018/p136...)

2. Garbage collection (The 90s were the height of GC hype, to the point that the JVM still struggles with "Don't worry. GC research will make it fast." design decisions.)

3. Error handling that feels like "Well, we know that exceptions were a mistake, so the only other option is C-style return values... but, hey, we can at least follow 90s Python's lead in supporting returning tuples." (Granted, exceptions DO bake in a fundamental assumption that all the world can be treated as single-threaded execution amenable to transactional rollback. → https://www.lighterra.com/papers/exceptionsharmful/)

4. No generics until they were pushed into it by things like people writing preprocessors that use the Canadian Aboriginal Syllabics characters that look like angle brackets. (https://www.reddit.com/r/rust/comments/5penft/parallelizing_...)

5. No sum types (Bear in mind that sum types have been around since ALGOL 68 and, on many fronts, C was a step backward that the entire industry copied)

6. Dependency management that was only a hair above "just `git clone` it into your project" for most of Go's lifetime

An example of such a reference would be this quote by rfiat at https://news.ycombinator.com/item?id=31603329

> It's interesting that you find Go to be Rust-adjacent. Setting aside the USPs of each language (goroutines and borrow checker respectively) and just speaking about the general experience of writing code, I find Go painful for all the reasons that I find Rust pleasant.

> The best summary I can give of Rust is that it was designed by people who learned from the mistakes of the programming languages that came before it. The best summary I can give of Go is to quote Rob Pike's response [0] to a request for syntax highlighting in the Go playground:

>> Syntax highlighting is juvenile. When I was a child, I was taught arithmetic using colored rods (http://en.wikipedia.org/wiki/Cuisenaire_rods). I grew up and today I use monochromatic numerals.

> [0] https://groups.google.com/g/golang-nuts/c/hJHCAaiL0so/m/kG3B...

dgunay's reply in that same thread ended on the summarization "I like Go and I feel very productive in it, but its commitment to simplicity is dogmatic in many ways and it very much is missing milestone advancements in PLs from the past several decades. It could easily have been made in the 90s."