Earlier quoted context omitted.
I appreciate your work on Rust, I find it to be a very interesting language. > I think each of these three languages have made the correct choice, given their design ideals. I feel that's kind of side-stepping the issue though. The approach that golang took could match their design goals, but it doesn't mean that those goals aren't a bad idea in the first place.
For any set of correctness-improving primitives in a language, you can practically always come up with some disjoint set of additional primitives, and then make the argument that the lack of those additional primitives constitute "bad design". Sometimes you'll even be right (it's not clear to me in this case). But it will almost always be a boring argument.
From Python to Go to Rust: an opinionated journey (2018)
61–70 of 78 posts
Re: From Python to Go to Rust: an opinionated journey (2018)
#62Earlier quoted context omitted.
For any set of correctness-improving primitives in a language, you can practically always come up with some disjoint set of additional primitives, and then make the argument that the lack of those additional primitives constitute "bad design". Sometimes you'll even be right (it's not clear to me in this case). But it will almost always be a boring argument.
In this case though, it's the addition of a "feature" that causes bugs, so lack of said feature will improve correctness.
Re: From Python to Go to Rust: an opinionated journey (2018)
#63Earlier quoted context omitted.
It's a pretty big annoyance with Go though. I hate that all struct fields are optional.
there are times when a nil struct field is useful, like for trees and json. very easy to require struct fields by using a constructor
Re: From Python to Go to Rust: an opinionated journey (2018)
#64Re: From Python to Go to Rust: an opinionated journey (2018)
#65Earlier quoted context omitted.
It's a pretty big annoyance with Go though. I hate that all struct fields are optional.
FWIW, I never had that problem, but I also tend to use constructors for my structs.
One use-case where this is really painful: I like to encode sum types in Go using an interface with a private dummy method + structs that implement that. I then have a function "match" that takes one function per struct. It's nice to be able to pass these functions as a record since it gets ugly, but due to Go allowing omitted functions to be nil, if I add a case to the sum, I open myself up to NPEs everywhere. If Go had a warning for missing struct fields, it would tell me all the places I'd need to handle a new case.
Re: From Python to Go to Rust: an opinionated journey (2018)
#66Earlier quoted context omitted.
Go has two mechanisms for initializing structs, name based and position based. type Sample struct { A int B int } can be initialized as Sample{A: 1, B: 2}, or Sample{1, 2}. The name-based method allows arbitrary elision of fields, which will be initialized to their zero value. This includes Sample{}, which will be interpreted as a name-based initialization that specified no fields. The position-based method requires…
The problem with using the positional method is that 1) It's much more difficult to read since you have to know the position of elements of the struct 2) You swap one compile time error for another: in the case you add and remove a field of the same type, it's entirely possible the program will compile fine if you use the positional initialization instead of the named one. #2 makes me think that the author would stil…
At least the Go editor I use (GoLand by JetBrains, one of the more popular ones) will display the names of all the fields in positional initializers inline with the code (just as they would be in a named initializer), so it's pretty much the same readability-wise. There's a special color for these automatic labels that indicates they aren't actually part of the document.
> in the case you add and remove a field of the same type, it's entirely possible the program will compile fine
True although I think it's easier to work around this (by fixing the compile errors from removing the old field before adding the new one).
Re: From Python to Go to Rust: an opinionated journey (2018)
#67> I compiled the code and … no error message. Everything went fine. But?! I just added a field to a struct, the compiler should say that my code is not good anymore because I’m not initializing the value where it should be! This is your big hangup with Go? You added a new field, didn’t use that field anywhere, and the compiler didn’t complain? I’ve heard a lot of valid criticisms of the language but this is a new one…
Go has two mechanisms for initializing structs, name based and position based. type Sample struct { A int B int } can be initialized as Sample{A: 1, B: 2}, or Sample{1, 2}. The name-based method allows arbitrary elision of fields, which will be initialized to their zero value. This includes Sample{}, which will be interpreted as a name-based initialization that specified no fields. The position-based method requires…
One other reasonable alternative for OP in Go might be to simply use initialization functions (NewSample() or sample.InitWithX()) for certain structs. It's a bit more flexible with the ability to have multiple initializers and non-zero default field values (and of course also solves the issue of generating compile errors in the rest of the code when new fields/parameters are added).
Re: From Python to Go to Rust: an opinionated journey (2018)
#68Earlier quoted context omitted.
In this case though, it's the addition of a "feature" that causes bugs, so lack of said feature will improve correctness.
Zeroing out uninitialized memory is a feature, one which significantly improves correctness over C/C++. Meanwhile, the scenario described in this blog post is shared by virtually every mainstream implementation language other than Rust.
On the other hand, golang does not have the ability to prevent "default constructors", and the fact that it has no ability to make types file private further makes this an issue.
Re: From Python to Go to Rust: an opinionated journey (2018)
#69Earlier quoted context omitted.
Zeroing out uninitialized memory is a feature, one which significantly improves correctness over C/C++. Meanwhile, the scenario described in this blog post is shared by virtually every mainstream implementation language other than Rust.
I don't see it in Java or C# for instance. You have to explicitly opt into it by (1) declaring default (parameter-less constructors), and (2) exposing fields you want mutated via setters. On the other hand, golang does not have the ability to prevent "default constructors", and the fact that it has no ability to make types file private further makes this an issue.
Re: From Python to Go to Rust: an opinionated journey (2018)
#70> I compiled the code and … no error message. Everything went fine. But?! I just added a field to a struct, the compiler should say that my code is not good anymore because I’m not initializing the value where it should be! This is your big hangup with Go? You added a new field, didn’t use that field anywhere, and the compiler didn’t complain? I’ve heard a lot of valid criticisms of the language but this is a new one…
Go has two mechanisms for initializing structs, name based and position based. type Sample struct { A int B int } can be initialized as Sample{A: 1, B: 2}, or Sample{1, 2}. The name-based method allows arbitrary elision of fields, which will be initialized to their zero value. This includes Sample{}, which will be interpreted as a name-based initialization that specified no fields. The position-based method requires…
Edit: spelling