Live data from Hacker News

Things about programming I learned with Go

mjk.space

141–150 of 157 posts

Re: Things about programming I learned with Go

#141
post #25

"Error theater" and zero initialized values, while understandable due to other design decisions, are the biggest source of frustration whenever I have to work on go code. Off topic from the article, I think, but what go has taught me about programming is that some parts of our industry are stuck in time and intellectually stagnant. Go is a better C. I would prefer Go over Python. But really, when the state of the art…

This sort of attitude is never going to win over people that you are talking about. I hate to bring politics into things, but it's like calling all Trump supporters hopeless and backwards. Yeah maybe they are, but they're going to react to that by never listening to anything you say again, so even though it's true, it's not helpful. The 'state of the art' is increasing, over-the-top complexity to a truly ridiculous l…

[deleted]

Re: Things about programming I learned with Go

#142
post #67

Earlier quoted context omitted.

Checked exceptions suck. Every method has to explicitly throw them up to a higher level where they can be handled causing tons of useless boilerplate. Its much better to just let unchecked exception bubble to a higher level of the app. This is a best practice in java so letting the exception bubble all the way back to the user is just poor programming.

That's exactly what you have to do in Rust anyway though. Except instead of just writing `throws SomeError` in the declaration line of the function, you have to annotate virtually every line of your function with `?` and wrap the return line in `Ok(...)`.

The ? RFC did include a "catch" construct, and there's been some discussion about doing something more like "throws SomeError." We'll see!

Re: Things about programming I learned with Go

#143
post #89
post #80

Earlier quoted context omitted.

You'd need generics and algebraic types to implement Result/Option

False. That feature allows a more efficient implementation, but (T, error) (or an equivalent struct) can be reasoned about in much the same way as Result . You don't need a tagged union when you can use the nil-ness of one of the two values in the tuple as the tag. Similarly, Option is just a wrapper around a nullable T.

The type you propose can inhabit both different variants at once, the entire point of Option is that it is either something or not.

Re: Things about programming I learned with Go

#144

Earlier quoted context omitted.

I don't really agree that it's inelegant to decide whether the reason for quitting is a success or an exception, or whether it's necessary. Like, you've either committed, in which case you shouldn't need to do any cleanup, or you haven't committed, in which case you need to clean up, right? If you have an object representing some sort of transaction, and you just have actually-do-all-the-work-at-once-on-commit-being-…

You are just making my point with that OOP mess (sorry). You are not using RAII to finish (meaning cleanup or rollback) the transaction. What we want actually executed in the end (in terms of control flow - not necessarily what we would be willing to code), is something like the following clean procedural code. do_some_foo(): start_transaction() r = do_thing_A() if r == CONFLICT: rollback() return r r = do_thing_B()…

There's nothing remotely object-oriented about what I wrote. I don't see any inheritance. I don't see any polymorphism. I don't see any virtual member functions.

And of course I'm using RAII to roll back the transaction. When the object is destroyed the vector is destroyed and the transaction isn't run.

It doesn't make any sense at all, quite frankly, to use RAII to do what you wrote there. That's not what RAII is for, nor is it what RAII is good at. RAII is for managing resources.

Re: Things about programming I learned with Go

#145

Earlier quoted context omitted.

Personally I loathe this style of programming. It's not that it's difficult, it just seems to obscure code a great deal. Writing this sort of thing in Rust: fun some_function(a: &A) -> Result { let c = foo(a)?; let d = foobar(a, c)?; Ok(if xfoo(c) { let e = blah()?; bar(d, e)? } else { baz(d)? }) } where you have to write every function in this pseudo-do-notation where 'return' is just wrapping the return expression…

> See how that's so much cleaner? No, I don't. I look at the former snippet and I can easily tell each and every function invocation that can cause SomeError. In your theoretical style, I have no idea whether foo, foobar, xfoo, bla, bar and/or baz will throw that error. I prefer explicit over implicit since I find it far more readable. > really horrible things like adding Option::map You can quibble about the names (…

>No, I don't. I look at the former snippet and I can easily tell each and every function invocation that can cause SomeError.

The reason that functions have type signatures is that you can read them. You can tell which functions can cause SomeError by going and reading their definitions.

>I prefer explicit over implicit since I find it far more readable.

'Explicit over implicit' is dogma. Rust requires you to annotate your code with gibberish in cases where it is not necessary.

>You can quibble about the names (Option and map), but Option is essentially the Maybe monad and map is bind, so you're kinda arguing against core functional programing constructs.

That's literally my entire point. The attitude that it's technically a Functor so it makes sense for it to be called map? No, it doesn't. It's not a map. You're not mapping over anything. Naming is important.

Calling it 'the Maybe monad' shows that you actually have no idea what you are talking about. It's not 'the Maybe monad'. The Maybe monad is the instance of Monad for Maybe. It is not Maybe itself.

The entire concept of having the literal 'Monad' word as a word in your language, a thing that you use in programming, is very stupid. Monad is not a useful or good abstraction. Maybe is a good abstraction. Or Optional, or Option, or whatever you decide to call it. But Monad is a bad abstraction. Abstracting over superficial syntactic similarities between completely different constructs is completely stupid.

The name being terrible is not 'quibbling' by the way. Naming is incredibly important. Calling it 'map' just shows how out of touch Rust is with real programmers.

Re: Things about programming I learned with Go

#146

Earlier quoted context omitted.

That's exactly what you have to do in Rust anyway though. Except instead of just writing `throws SomeError` in the declaration line of the function, you have to annotate virtually every line of your function with `?` and wrap the return line in `Ok(...)`.

The ? RFC did include a "catch" construct, and there's been some discussion about doing something more like "throws SomeError." We'll see!

It's far too late for "we'll see".

Re: Things about programming I learned with Go

#147
post #107
post #70

Earlier quoted context omitted.

>The Go version of error handling requires less typing overall Do you mean as compared to using exceptions in a language like Python or Java? If so, can you give an example of code that does the same task, in both types of languages, to make this more clear? Thanks.

I was mostly thinking of Java. Ignoring an exception would be done with try {....} catch (Exception e) {}, while in Go, you would do: x,_ := f(...). And if you want to check a returned error I think the if err!=nil {...} is still a bit less typing than the Java version, and you don't have to declare checked exceptions you might throw.

In Go, if you call three functions you need to repeat the

  x, err := do_something()
  if err != nil {
          return nil, err
  }
ceremony three times. In Java it happens by default, because the language designers agreed this is by far the most common case.

Ignoring an error is almost always a serious mistake, so the fact that Go makes it easy and not blatant is not a good thing.

Re: Things about programming I learned with Go

#148

Earlier quoted context omitted.

> I'm not sure what you imply. Most OOP languages where people tell you not to use inheritance, but composition instead, so java, c++, c#, etc. In those languages inheritance can be used to create forms of product types, but also to share and override behaviour hierarchically. They can also create sum types, and all possibility of hybrids, like weird mix of sum and product types, partially closed, etc. My point wasn'…

Okay, but its not, not from the perspective the best practice comes from. The most common use cases for object inheritance can be delivered with object composition instead. This is much more like loop vs recursion.

The dominant use case for inheritance is polymorphism, which composition cannot do.

Re: Things about programming I learned with Go

#149
post #107

Earlier quoted context omitted.

I was mostly thinking of Java. Ignoring an exception would be done with try {....} catch (Exception e) {}, while in Go, you would do: x,_ := f(...). And if you want to check a returned error I think the if err!=nil {...} is still a bit less typing than the Java version, and you don't have to declare checked exceptions you might throw.

In Go, if you call three functions you need to repeat the x, err := do_something() if err != nil { return nil, err } ceremony three times. In Java it happens by default, because the language designers agreed this is by far the most common case. Ignoring an error is almost always a serious mistake, so the fact that Go makes it easy and not blatant is not a good thing.

>ceremony three times. In Java it happens by default,

What happens by default? Not clear. (I know Java, but not up to date with recent versions.)

>Ignoring an error is almost always a serious mistake

Agreed.

Re: Things about programming I learned with Go

#150
post #149

Earlier quoted context omitted.

In Go, if you call three functions you need to repeat the x, err := do_something() if err != nil { return nil, err } ceremony three times. In Java it happens by default, because the language designers agreed this is by far the most common case. Ignoring an error is almost always a serious mistake, so the fact that Go makes it easy and not blatant is not a good thing.

>ceremony three times. In Java it happens by default, What happens by default? Not clear. (I know Java, but not up to date with recent versions.) >Ignoring an error is almost always a serious mistake Agreed.

In Java, an exception outside a catch block automatically stops the method and raises the exception to the caller, and then their caller, and so on. In Go you have to write this after every function call (except the tiny minority that can only panic).
Post reply on HN