Live data from Hacker News

Declined Proposal: A built-in Go error check function, “try”

github.com

351–360 of 425 posts

Re: Declined Proposal: A built-in Go error check function, “try”

#351

Earlier quoted context omitted.

Ok let me tell you the criteria. There are two. First: The monad allows for composition of functions. Returning two values does not. It breaks the flow of a function pipeline and forces you to handle every error in the same way. Second: Extracting the value via pattern matching guarantees that the error will either be handled or used correctly. This is a way to 100% guarantee that there are No runtime errors. That's…

I'm interested in the zero runtime errors piece - how would a language with the maybe monad handle an out-of-memory error at runtime?

There is a way of which (to my knowledge) is not implemented in any technology.

Presuming you know how the maybe monad (or similar named monads) handles errors. A MaybeOutOfMemoryError works in a similar way in the sense that any attempt to use the value meaningfully will force you to handle the error.

   data MaybeOutOfMemoryError a = OutOfMemoryError | Some a 

   ioFunction :: MaybeOutOfMemoryError a -> IO

   ioFunction OutOfMemoryError = println "ERROR"
   ioFunction Some _ = println "No ERROR"
exhaustive pattern matching with the error flag enabled makes it so that if you forget the OutOfMemoryError case an error will occur during compile time.

Any function that can potentially trigger a memory error should be forced to be typed like this. However in programming, ALL functions can potentially do this, and side effects outside of the scope of the function (total memory available) will trigger it meaning that the only way to do this effectively is to make ALL functions typed this way. Which is inconvenient to say the least.

That being said you can just type the main function as something that can only accept this monadic value forcing users to wrap this handling in a top level function:

   myWrittenProgram :: MaybeOutOfMemoryError a
    -- not defined in this example

    -- main is forced to be typed this way just like how in haskell it is forced to be typed IO ()
   main :: MaybeOutOfMemoryError a -> IO ()
   main Some a = printLn a
   main OutOfMemoryError = printLn "Error out of memory"
Obviously the above has some issues with the rest of haskell syntax and the way things are done, but I'm just showing you a way where it is possible to make sure that a memory runtime error does not happen (that is an unhandled runtime error).

That being said unless you know haskell or know what a maybe monad is, you wouldn't be able to fully comprehend what I said. Exception monads exist in haskell, but nothing is forcing the main function to be typed this way.

Re: Declined Proposal: A built-in Go error check function, “try”

#352
post #70

Earlier quoted context omitted.

The bad ergonomics? Golang is an excellent language.

I don't think it qualifies for that name.

That's your opinion, in the mean time a lot of us will keep producing good applications using Golang and enjoying it :)

There's no amount of downvote that will change that fact.

Re: Declined Proposal: A built-in Go error check function, “try”

#353

Earlier quoted context omitted.

> Littering your code with try-catch is what makes exceptions infeasible for error handling. I honestly don't see the big difference between littering your code with if/else blocks versus littering them with try/catch blocks. Can you elaborate?

If/else provides a clear and easy to follow control flow. try/catch is like a roaming goto that works it's way back up your stack in ways you can't predict. http://www.lighterra.com/papers/exceptionsharmful/

I don't understand the argument that stack unwinding is unpredictable -- the most naive implementation of exceptions would just be multiple-function returns with automatic propagation (effectively the same as automatically putting the try! macro on every call in Rust).

Nothing about try/catch is like a "roaming goto".

Re: Declined Proposal: A built-in Go error check function, “try”

#355

Earlier quoted context omitted.

Slice operations are deliberately verbose in this way so as not to hide the cost of allocation that goes along with them. They are not common in code, but they do make good strawmen when you want to counter general points with specific ones.

Aligned incentives? Making a “simple” operation as hard to write as it will be on the machine.

While not objectively a bad thing, that's at the crux of the problem many have with Go: it sets the bar very, very low for getting in your way instead of trusting you to be even slightly competent. Knowing basic data structures is engineering 101,and any engineer who'd (eg) blindly use std::find on a vector or "in" on a list in performance-critical code without understanding it isn't someone who should be committing code without review in any case. Inefficient data structure operations are also precisely the kind of thing that's easy to catch in code review.

Don't get me wrong, this isn't a general-purpose argument and I'm not one of those people who thinks that the language should completely get out of your way: eg I'm not a Rust user but its unergonomic handling of memory safety seems far preferable to the ease with which you can shoot yourself in the foot with C++. I definitely see the appeal of Go's handholding in a directional sense. But the degree to which it takes it makes it feel like an unserious or educational language, unnecessarily difficult to get actual work done in, like Javascript but for the exact opposite reasons (and to be clear, Javascript is INFINITELY worse).

This makes it sound like Im more negative on Go than I am, but I think it's the first time I've been able to articulate what deflated my initial interest in it and kept me away from it. Perhaps if feel differently if I had still been a student and new to programming when Golang was released.

Re: Declined Proposal: A built-in Go error check function, “try”

#356
post #204

Earlier quoted context omitted.

If only there was a way to make a single function work with multiple different types. A way to "genericize" it, you might say. Alas, that's obviously completely impossible. Such a thing is beyond the capabilities of us mortal programmers. But maybe one day PL researchers will discover a way. One day...

Rob Pike would rather use a for loop than map or filter.. so yeah don’t dream too big https://github.com/robpike/filter

That's kind of awesome code though. I learned things about go looking through how he implemented reduce. Thank you for sharing it.

Re: Declined Proposal: A built-in Go error check function, “try”

#357
post #61

Earlier quoted context omitted.

>So long as we can all agree that it feels super bad, I guess this is fine. Actually, I don't think everyone agrees it feels super bad. I personally like having all of my error handling be explicit, painfully explicit even. >approaches the Java world back with checked exceptions where principle trumped ergonomics. I also have to disagree here. To me, checked exceptions are the worst of both worlds. Here you have addi…

> Go doesn't even really force you to check your errors, it just makes it harder to accidentally not check them. Quite the opposite. You have to explicitly ignore exceptions, whereas it’s easy to accidentally miss an error in Go. For example, how many times have you seen this? defer f.Close() Close() returns an error; this code ignores it.

To be fair, reporting that cleanup also failed with a different error is inherently complicated, and so many people got the try-finally version wrong that Java finally added try-with-resources and Throwable#addSuppressed.

Re: Declined Proposal: A built-in Go error check function, “try”

#358

Earlier quoted context omitted.

So long as we can all agree that it feels super bad, I guess this is fine Exceptions feel super good, even as you're taking too many shortcuts and glossing over things. Proper handling of the unhappy paths is often going to feel like a slog, because it often is complicated, and it's often a slog. Glossing over error handling in golang can feel bad exactly when it should.

In some contexts, exceptions are just cleaner and easier. If I’m writing a web backend, my error handling is going to almost always be, “stop trying to do things and generate a 4xx/5xx response”. Throwing an exception from anywhere and then handling it at the top of the request handling does that without having to tediously carry errors all the way up the call stack.

In some contexts, exceptions are just cleaner and easier.

Definitely. The question is, are the benefits in those contexts worth the cost of the potential abuses? As a codebase and company get larger and larger, the higher the probability that a problem will get into the codebase.

There is an analogy here with C++ templates and with method_missing meta-programming. There are some contexts where they make things a lot easier. However, in a large codebase, the probability that some programmer, somewhere is going to cause a costly problem with a bit of nifty overreach goes up and up.

Re: Declined Proposal: A built-in Go error check function, “try”

#359

Earlier quoted context omitted.

The controversy may have died down, but the impact on code written would have been permanent. There's a lot of value to there being "one way to do things", even when it's not the best way from any particular point of view. Go holds this principle higher than most other languages and I think that should be either embraced, or one should look elsewhere - and I'm saying that as someone who "looked elsewhere".

Agreed, no one is forced to use Go. I think it is refreshing to see a language like Go. You don't want all languages to asymptotically approach each other in features. We need diversity in our languages, that way you have flavors to choose from.

> no one is forced to use Go.

I suspect some people are. Languages have network effects, which get stronger when FFI is uncommon. My team and codebase mostly keep me on Java even though I find Kotlin clearer in every way and I'd love to get better with Scala and Haskell. If for some reason my team switched to something like Go or VB I'd have to find another job or else put up with it.

Re: Declined Proposal: A built-in Go error check function, “try”

#360

Earlier quoted context omitted.

One foundational principle of Go is that the sad path is at least as important, and maybe more important, than the happy path. The best Go programmers I know write the sad path of their programs first, and then backfill the happy-path logic. So: > you only need to write [error checking] when you actually have something meaningful to do. Although it's the subject of a lot of ridicule, `if err != nil { return err }` is…

> `if err != nil { return err }` is actually bad Go code, and not often written by good Go programmers. Like the people who wrote the Go stdlib? Because that's filled with those - just look at the net/* packages.

One distinction that is often made by core team members is that you only need to annotate errors at package boundaries, and that returning unannotated errors within a package is fine. But in most code, the packages are not so well-defined, or well-thought-out, or sacrosanct, that they represent a good proxy for annotation decisions.

I would much rather have an error with too much or duplicate annotation than one with not enough. And I would further argue that, yes, in the stdlib, errors are generally under-annotated.

Post reply on HN