Live data from Hacker News

Why Go Can't Try

niketpatel.com

41–50 of 74 posts

Re: Why Go Can't Try

#41
Coming from Java/C# with exceptions Go felt like an improvement

Most languages eventually end up confusing 'try-catch', errors, exceptions, handle?, re-throw?... Together with most programmers mixing internal erros, business errors, transient... Creating complex error types with error factories, if and elses... Everything returning the same simple error is simply genious

Also a lot of zig posts are tone def like this. "Oh look something so simple and we're the first to think about it. We must be really good"

Re: Why Go Can't Try

#42

Earlier quoted context omitted.

> every type must have a default/zero value in Go Hot take, maybe, but this is one of the few "mistakes" I see with Go. It makes adding QoL things like you mentioned difficult, requires shoehorning pointers to allow for an unset condition, some types don't have a safe default/zero value like maps, and makes comparisons (especially generic) overly complex.

Go specifically does not want to add QoL things because it means the compiler team has to spend time implementing that extra syntax and semantics versus making a minimal set of features better.

The problem with the zero value business is that it also makes adding these QoL things in libraries difficult or outright impossible. Case in point, I tried building a library for refinement types, so you can have a newtype like,

  type AccountName string
except you write it like (abridged)

  type AccountName refined.Scalar[AccountName, string]

  func (AccountName) IsValid(value string) bool {
    return accountNameRegexp.MatchString(value)
  }
and that enforces an invariant through the type system. In this case, any instance of type AccountName needs to hold a string conforming to a certain regular expression. (Another classical example would be "type DiceRoll int" that is restricted to values 1..6.)

But then you run into the problem with the zero value, where the language allows you to say

  var name AccountName // initialized to zero value, i.e. empty string
and now you have an illegal instance floating around (assuming for the sake of argument that the empty string is not a legal account name). You can only really guard against that at runtime, by panic()ing on access to a zero-valued AccountName. Arguably, this could be guarded against with test coverage, but the more insidious variant is

  type AccountInfo struct {
    ID int64 `json:"id"`
    Name AccountName `json:"name"`
  }
When you json.Unmarshal() into that, and the payload does not contain any mention of the "name" field, then AccountName is zero-valued and does not have any chance of noticing. The only at least somewhat feasible solution that I could see was to have a library function that goes over freshly unmarshaled payloads and looks for any zero-valued instances of any refined.Scalar type. But that gets ugly real quick [1], and once again, it requires the developer to remember to do this.

[1] https://github.com/majewsky/gg/blob/refinement-types-4/refin...

So yeah, I do agree that zero values are one of the language's biggest mistakes. But I also agree that this is easier to see with 20 years of hindsight and progress in what is considered mainstream for programming languages. Go was very much trying to be a "better C", and by that metric, consistent zero-valued initialization is better than having fresh variables be uninitialized.

Re: Why Go Can't Try

#43

Earlier quoted context omitted.

Go specifically does not want to add QoL things because it means the compiler team has to spend time implementing that extra syntax and semantics versus making a minimal set of features better.

The problem with the zero value business is that it also makes adding these QoL things in libraries difficult or outright impossible. Case in point, I tried building a library for refinement types, so you can have a newtype like, type AccountName string except you write it like (abridged) type AccountName refined.Scalar[AccountName, string] func (AccountName) IsValid(value string) bool { return accountNameRegexp.Matc…

You're missing the point, Go does not want these QoL features. Arguing about why they are hard to add is pointless because, philosophically, they are undesirable and not going to be accepted.

Re: Why Go Can't Try

#44
The plot seems to get real lost in the article.

Sure … it is true that Go errors can carry data, and Zig ones perhaps do not, but I don't see how that is what disqualifies a `try` from being possible. Rust's errors are rich, and Rust had `try!` (which is now just `?`).

The article's reasoning around rich errors seems equally muddled.

> In Zig, there's no equivalent. If both calls fail with error.FileNotFound, the error value alone can't tell you which file was missing.

Which is why I'm not a huge fan of Zig's error type … an int cannot convey the necessary context! (Sometime I'd've thought C had so thoroughly demonstrated as bad with, e.g., `mkdir` telling people "No such file or directory." — yeah, no such directory, that's why I'm calling `mkdir` — that all new designs would not be limited to using integer error codes.)

But then we go for …

> Zig's answer is the Error Return Trace: instead of enriching the error value, the compiler tracks the error's path automatically.

But the error's "path" cannot tell you what file was missing, either

> It tells you where the error traveled, not what it means. Rather than enriching the error value, Zig enriches the tooling.

Sure … like, again, a true-ish statement (or opinion), but one that just doesn't contribute to the point, I guess? A backtrace is also useful, but having the exact filename is useful, too. It depends on the exact bug that I'm tracking: sometimes the backtrace is what I need, sometimes the name of the missing file is what I need. Having both would be handy, depending on circumstance, and the call stack alone does not tell you the name of the missing file.

… how does either prevent a `try` statement?

We try to argue that somehow the stdlib would need to change, but I do not see how that can be. It seems like Go could add try, as syntactic sugar for the pattern at the top of the article. (& if the resulting types would have type errored before, they could after sugaring, etc.)

Re: Why Go Can't Try

#45
I keep feeling this feeling and it depresses me. I start reading an article and then gradually realise it's a load of AI slop, but by the time I get that realisation I've already wasted several minutes of my life. It's a sinking feeling like I've been duped, but not for anybody's gain - the "author" isn't earning anything from my view, they've just wasted my time for no reason. Even my misfortune is valueless. It happens again and again and again, it's wearing me down.

What are we doing here?

Re: Why Go Can't Try

#46
post #30

The programmer is explicitly throwing away the error returned by ReadFile (using the underscore) in the criticism of Go. data, _ := os.ReadFile(path) Saying that is not explicit is just wrong.

I think the argument is that the compiler does not enforce that the error must be checked. It's just a convention. Because you know Go, you know it's convention for the second return value to be an error. But if you don't know Go, it's just an underscore. In a language like Rust, if the return type is `Result `, the caller cannot access the `MyDataType` without using some code that acknowledges there might be an erro…

When you see .unwrap in Rust code, you know it smells bad. When you see x, _ := in Go code, you know it smells bad.

> But if you don't know Go, it's just an underscore.

And if you don't know rust, .unwrap is just a getter method.

Re: Why Go Can't Try

#47

The Go team has discussed syntactic sugar for error handling many times. They're not against it, they're just holding out for a proposal that checks a lot of boxes and makes everyone happy, which hasn't happened yet.

I they wanted error handling they would have thought for a bit then picked a good enough solution. "We only want 'X but perfect'" is the same as "we don't want X".

Re: Why Go Can't Try

#48
post #27

These AI written articles carry all the features and appearance of a well reasoned, logical article. But if you actually pause to think through what they're saying the conclusions make no sense. In this case no, it's not the case that go can't add a "try" keyword because its errors are unstructured and contain arbitrary strings. That's how Python works already. Go hasn't added try because they want to force errors to…

It is simpler than that. Go hasn't added "try" because, much like generics for a long time, nobody has figured out how to do it sensibly yet. Every proposal, of which there have been many, have all had gaping holes. Some of the proposals have gotten as far as being implemented in a trying-it-out capacity, but even they fell down to scrutiny once people started trying to use it in the real world. Once someone figures…

> nobody has figured out how to do it sensibly yet.

In general or specifically in Go?

Re: Why Go Can't Try

#49

Earlier quoted context omitted.

Go specifically does not want to add QoL things because it means the compiler team has to spend time implementing that extra syntax and semantics versus making a minimal set of features better.

The problem with the zero value business is that it also makes adding these QoL things in libraries difficult or outright impossible. Case in point, I tried building a library for refinement types, so you can have a newtype like, type AccountName string except you write it like (abridged) type AccountName refined.Scalar[AccountName, string] func (AccountName) IsValid(value string) bool { return accountNameRegexp.Matc…

Go was trying to be a better c++. In c++ there are infinity different constructors and that was too complicated, so they made a language with only one constructor. Go isn't the way it is because nobody knew any better, it's because they deliberately chose to avoid adding things that they thought weren't beneficial enough to justify their complexity.

Re: Why Go Can't Try

#50
post #7

I really hate it when people try to justify Go’s design decisions. Try would be very useful. The real reason why is because the Go team refuses to take any lesson from any other programming language except for C. That’s why there are so many questionable decision. Also I was a little disappointed there was no mention of panics which are one such questionable decision. Also the author stopped trying to cover up their…

> the Go team refuses to take any lesson from any other programming language except for C.

Go acknowledges taking the design of the object file format from, IIRC, Modula-2. You are very wrong.

Post reply on HN