Live data from Hacker News

Notes on the Go translation of Reposurgeon (2020)

gitlab.com

31–40 of 155 posts

Re: Notes on the Go translation of Reposurgeon (2020)

#31

Great writeup. Some of the points are moot now that generics are being released, but some very valid concerns. I would also add that Enums + Exhaustive Switch is a very very weak area in Go that would really benefit the language a ton. I've used those features in other languages and that's one of the things I miss the most, especially when dealing with a ton of web API's that have a defined set of values for properti…

> Able to have the confidence that we're checking for every situation that could occur on an enum type across the codebase is one less thing I need to worry about. golangci-lint ( https://github.com/golangci/golangci-lint ) is an absolute must, and includes https://github.com/nishanths/exhaustive which will check this for you.

my 50 cents:

I'd rather just use go vet + staticcheck. Way simpler, no complex configuration, and no license concerns :)

and then you can create a file like the following and add whatever analyzer provides value for your specific case (including this exhaustive), easily. Example: https://github.com/FiloSottile/mkcert/blob/master/analysis.g...

Re: Notes on the Go translation of Reposurgeon (2020)

#32
post #9

What a delight to read, even as somebody who has barely used Go. I really appreciate the author's self-awareness as demonstrated in things like "Expected problems that weren’t". The bits about exceptions and typing remind me of an open question I have about Go: to me it mainly looks like a language for well-understood problems. Static typing and the lack of ability to do broad, high-level exception catching seem to m…

I feel like strong typing _helps_ when exploring a new domain, as it forces you to really think about the data you're operating on. In a language like Perl or Python, it's so easy to just throw around a bunch of hashes/dicts and that can get messy really quickly.

I don't miss _exceptions_ in Go but after using Rust for a while I've come to really love Rust's `Option` and `Result` types. They're more ergonomic and expressive than Go's errors-as-values, and the use `Option` also eliminate `nil` entirely, which has been a regular source of runtime panics in every large Go codebase I've worked on.

Re: Notes on the Go translation of Reposurgeon (2020)

#33
post #30
post #28

> What I really missed was generic map-function-over-slice Me too, and mapping a map, a channel, etc. With generics, things will be easier, we can have iterators, even lazy iterators, but there will still be no type inference in lambdas for arguments and return values and no easy currying, so things will still be awkward, but better. > Keyword arguments You can kind of do that by passing a struct as an argument, and…

> You can kind of do that by passing a struct as an argument, and represent the optionalness by having a pointer in the struct. That's still awkward, you can't easily make a pointer to an integer or string literal, you need a separate helper function for each primitive type. Overall it could be nicer. I think using a builder is a better option in Go if you have more than 2-3 arguments. > Yeah, I refer to it as Algebr…

> I think using a builder is a better option in Go if you have more than 2-3 arguments.

But then you need to write all the setters, and something that was supposed to be simple, a function, becomes a whole contraption with a bunch of auxiliary code. Personally I would avoid that, and I definitely wouldn't make it a rule of thumb to use builders in every function with more than 2-3 arguments (maybe you meant something else).

Re: Notes on the Go translation of Reposurgeon (2020)

#34
post #30
post #28

> What I really missed was generic map-function-over-slice Me too, and mapping a map, a channel, etc. With generics, things will be easier, we can have iterators, even lazy iterators, but there will still be no type inference in lambdas for arguments and return values and no easy currying, so things will still be awkward, but better. > Keyword arguments You can kind of do that by passing a struct as an argument, and…

> You can kind of do that by passing a struct as an argument, and represent the optionalness by having a pointer in the struct. That's still awkward, you can't easily make a pointer to an integer or string literal, you need a separate helper function for each primitive type. Overall it could be nicer. I think using a builder is a better option in Go if you have more than 2-3 arguments. > Yeah, I refer to it as Algebr…

> Except you can't really do this with interfaces

Apparently they decided that it would be too confusing to have variant types alongside interfaces for some reason, and they claim that interfaces handle a lot of the use cases of variants:

https://go.dev/doc/faq#variant_types

Re: Notes on the Go translation of Reposurgeon (2020)

#35
post #33
post #30

Earlier quoted context omitted.

> You can kind of do that by passing a struct as an argument, and represent the optionalness by having a pointer in the struct. That's still awkward, you can't easily make a pointer to an integer or string literal, you need a separate helper function for each primitive type. Overall it could be nicer. I think using a builder is a better option in Go if you have more than 2-3 arguments. > Yeah, I refer to it as Algebr…

> I think using a builder is a better option in Go if you have more than 2-3 arguments. But then you need to write all the setters, and something that was supposed to be simple, a function, becomes a whole contraption with a bunch of auxiliary code. Personally I would avoid that, and I definitely wouldn't make it a rule of thumb to use builders in every function with more than 2-3 arguments (maybe you meant something…

> But then you need to write all the setters, and something that was supposed to be simple, a function, becomes a whole contraption with a bunch of auxiliary code. Personally I would avoid that, and I definitely wouldn't make it a rule of thumb to use builders in every function with more than 2-3 arguments (maybe you meant something else).

Yeah, it's tedious, but that's Go for you ;)

Rust has the same issue, but there are macros libraries that will create the builder for you based on the struct definition, so it's _very_ trivial to create these builders.

You could do the same with codegen for Go, but this always feels much worse to me than using macros for a number of reasons like having to install a separate tool, checking in generated files, making people run `go generate` after some (but not all) changes, etc.

Re: Notes on the Go translation of Reposurgeon (2020)

#36
post #23

Earlier quoted context omitted.

Honestly, you don't notice it once you get into the Go mindset. The exception handling looks onerous, and is a pain at the start. But it doesn't take long to get used to it, and then (for me anyway) it becomes second-nature. Everything returns an error, and you have to handle that error (even if only passing it up again). Static typing is more "fun" when you're exploring new concepts, but interfaces are the key. Defi…

> But it doesn't take long to get used to it I did get used to it, but all the if err != nil { return nil, err } sometimes taking up half or more of the vertical space of a function is still an eyesore to me, even after writing a quite substantial amount of Go.

This exactly. I haven't written enough Go to be really annoyed by the more subtle things in the post, but it'd really be nice if they could come up with some syntax sugar for that kind of like Rust's ? helper.

Maybe the Go ? is allowed within any function whose last return value is an error on any function call whose last return value is also an error. Call it with ? at the end and accept all but the last return value. At runtime, if the err is not nil, then it returns from the function, supplying the err value and nil for any other return values.

Re: Notes on the Go translation of Reposurgeon (2020)

#37
post #34
post #30

Earlier quoted context omitted.

> You can kind of do that by passing a struct as an argument, and represent the optionalness by having a pointer in the struct. That's still awkward, you can't easily make a pointer to an integer or string literal, you need a separate helper function for each primitive type. Overall it could be nicer. I think using a builder is a better option in Go if you have more than 2-3 arguments. > Yeah, I refer to it as Algebr…

> Except you can't really do this with interfaces Apparently they decided that it would be too confusing to have variant types alongside interfaces for some reason, and they claim that interfaces handle a lot of the use cases of variants: https://go.dev/doc/faq#variant_types

Yeah, "for some reason" is a good summary of many Go decisions.

Rust has both (traits are somewhat like interfaces) and I don't feel like it's too painful, though using the trait type in function signatures is a lot more involved than in Go, and I still don't fully understand all the nuances. But the complexity isn't because of any overlap between traits and sum types.

Re: Notes on the Go translation of Reposurgeon (2020)

#38
post #36
post #23

Earlier quoted context omitted.

> But it doesn't take long to get used to it I did get used to it, but all the if err != nil { return nil, err } sometimes taking up half or more of the vertical space of a function is still an eyesore to me, even after writing a quite substantial amount of Go.

This exactly. I haven't written enough Go to be really annoyed by the more subtle things in the post, but it'd really be nice if they could come up with some syntax sugar for that kind of like Rust's ? helper. Maybe the Go ? is allowed within any function whose last return value is an error on any function call whose last return value is also an error. Call it with ? at the end and accept all but the last return valu…

https://go.googlesource.com/proposal/+/master/design/go2draf...

I don’t think it went anywhere, unless I missed it.

Re: Notes on the Go translation of Reposurgeon (2020)

#39
It's not surprising that the code base grew when reimplemented in golang. It would have probably been even shorter had it been rewritten in Python itself.

Just the other day, I was able to condense over 15 lines of golang code into 3 lines (could also have been 2 lines) in a Python-like syntax, both reducing code length, and substantially increasing readability as it would make the underlying logic clearly stand out instead of having several loop and map constructs.

Re: Notes on the Go translation of Reposurgeon (2020)

#40
post #32
post #9

What a delight to read, even as somebody who has barely used Go. I really appreciate the author's self-awareness as demonstrated in things like "Expected problems that weren’t". The bits about exceptions and typing remind me of an open question I have about Go: to me it mainly looks like a language for well-understood problems. Static typing and the lack of ability to do broad, high-level exception catching seem to m…

I feel like strong typing _helps_ when exploring a new domain, as it forces you to really think about the data you're operating on. In a language like Perl or Python, it's so easy to just throw around a bunch of hashes/dicts and that can get messy really quickly. I don't miss _exceptions_ in Go but after using Rust for a while I've come to really love Rust's `Option` and `Result` types. They're more ergonomic and exp…

Sum types are a thing I don't want to be without again. Not only the built in Option and Result, but once you're in the mindset you find they're the right fit for other problems too.

In Rust itself, writing stuff where I actually care whether my structure is 16 or 20 bytes because I need to fit hundreds of millions of them into RAM, I like that Sum types ensure Option is the same size as usize, by reasoning that 0 isn't a valid NonZeroUsize and so it can signal None. However on a language like Go I don't miss that - what I do miss is the fact that in Rust I can't mistakenly end up with None(actually_something) or both an error and the result that shouldn't be there if there was an error.

Post reply on HN