Live data from Hacker News

Notes on the Go translation of Reposurgeon (2020)

gitlab.com

41–50 of 155 posts

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

#41

The article mentions that Go, OCaml, or a compiled lisp were considered for this project. I wonder why Rust wasn't on that list. It seems to cover every concern that is raised here except for keyword arguments (which are high on my list of desired Rust features too). I guess maybe they were worried about the lack of GC, but my experience has been that's it's generally quite easy to port code from dynamic languages li…

Here is what esr wrote about Rust in early 2017: http://esr.ibiblio.org/?p=7294 http://esr.ibiblio.org/?p=7303

> A lot of Rustaceans don’t seem to grasp why, when the question is “where do I get feature X?” the answer “oh, there are 23 crates for that” is objectively terrifying.

This is exactly the impression I have gotten from the crates system every time I've looked. It happens for things as foundational as mmap. Also terrifying: The plethora of highly-recommended crates that have not yet committed to a stable API (ie, are still semantically on version 0.X).

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

#42
post #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…

I think you have to be very careful before claiming readability gains from fewer lines of code. I've done a lot of Python programming and for simple things like mapping a single function over a list, a list comprehension or generator expression can indeed be a tiny bit more readable than a for loop, but combining that with some filtering or flattening and colleagues (and my future self) get frustrated. I've seen the same thing with overly fancy iterator chaining in Rust.

There's some temptation to think that terse==readable, but in practice this rarely extends beyond the simplest cases.

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

#43

Earlier quoted context omitted.

Here is what esr wrote about Rust in early 2017: http://esr.ibiblio.org/?p=7294 http://esr.ibiblio.org/?p=7303

> A lot of Rustaceans don’t seem to grasp why, when the question is “where do I get feature X?” the answer “oh, there are 23 crates for that” is objectively terrifying. This is exactly the impression I have gotten from the crates system every time I've looked. It happens for things as foundational as mmap. Also terrifying: The plethora of highly-recommended crates that have not yet committed to a stable API (ie, are…

I agree, but at the same time things tend to stabilize over time as the community settles around the best packages. The real thing to fear is the relative instability of Rust at the present moment (for certain things, like async), but the overall trajectory seems promising.

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

#44

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…

Strongly agree here. I'd rather have this than generics, personally. Having to implement my own sum types every time is laborious (moreso than most boilerplate that people complain about) and it's also hard for users to understand (what are all of the permutations?) and extend (I added a new permutation; where are all of the sites I need to update?).

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

#45
post #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…

I think you have to be very careful before claiming readability gains from fewer lines of code. I've done a lot of Python programming and for simple things like mapping a single function over a list, a list comprehension or generator expression can indeed be a tiny bit more readable than a for loop, but combining that with some filtering or flattening and colleagues (and my future self) get frustrated. I've seen the…

I didn't yet get around to writing Go in any significant capacity (it's not in an interesting spot for me) but I've had to read some and to me it seems like about half of all Go code does approximately nothing. It seems really weird to me that Go doesn't have a Result/Optional type (or sum types in general) and instead prefers multiple return values instead, and consequentially does not have error-handling operators but requires if err != nil repeated approximately 9000 times per file.

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

#46

Earlier quoted context omitted.

Here is what esr wrote about Rust in early 2017: http://esr.ibiblio.org/?p=7294 http://esr.ibiblio.org/?p=7303

> A lot of Rustaceans don’t seem to grasp why, when the question is “where do I get feature X?” the answer “oh, there are 23 crates for that” is objectively terrifying. This is exactly the impression I have gotten from the crates system every time I've looked. It happens for things as foundational as mmap. Also terrifying: The plethora of highly-recommended crates that have not yet committed to a stable API (ie, are…

I’m not sure that’s a great example. mmap(2) is a swiss army knife of a function. There are many crates that build all kinds of things on top of mmap, and they’re not all interchangeable. Allocators, file io, gpio, actual virtual memory mappings.

My view is that when you develop a product, you have to own everything. The users don’t care if the bug comes from code you wrote, or code in a library, or the language’s standard library, or the OS. You have to fix the bug no matter what caused it. It doesn’t matter if the code came from a vendor or a language designer or stack overflow; you are the one responsible for fixing it if something goes wrong. Non est salvatori salvator, etc.

With that perspective, I don’t think that 23 crates is terrifying. I’m going to look them all over and either pick one, or write the 24th crate myself. The result is the same either way.

I do agree with you about APIs though. It is nice to find a crate where the author has had the confidence to stabilize their API and declare the version to be 1.x instead of 0.x. But at the same time I recognize that getting to that point requires some real software to use the crate, to create the feedback loop. If nobody ever used a 0.x crate, no crate would ever get that feedback.

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

#47

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…

go-sumtype[0] has completeness checking for sealed interfaces.

[0] https://github.com/BurntSushi/go-sumtype

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

#48
One thing that the people saying "just use a struct for keyword arguments" are missing is that structs should signal intent, i.e. "this is a concrete concept in the system." A Repository, Commit, Message, Person, etc. struct are all concepts in the domain, whereas "the arguments for this particular function" is not. I think Go people are allergic to writing code that does anything other than functionally work.

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

#49
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…

Python is strongly typed, not weakly typed. What you are talking about is static typing, which Python is not; Python is dynamically typed. Please do not confuse the two concepts.

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

#50

Earlier quoted context omitted.

I think you have to be very careful before claiming readability gains from fewer lines of code. I've done a lot of Python programming and for simple things like mapping a single function over a list, a list comprehension or generator expression can indeed be a tiny bit more readable than a for loop, but combining that with some filtering or flattening and colleagues (and my future self) get frustrated. I've seen the…

I didn't yet get around to writing Go in any significant capacity (it's not in an interesting spot for me) but I've had to read some and to me it seems like about half of all Go code does approximately nothing. It seems really weird to me that Go doesn't have a Result/Optional type (or sum types in general) and instead prefers multiple return values instead, and consequentially does not have error-handling operators…

This seems like a real sticking point for a lot of people. Personally, I don't seem to think about code volume in units of "lines" but rather in units of "complexity" and "locality". I would like to see Result and Optional types, but in practice everyone understands that (nil, err) is the same as Result::Err and that (*T, nil) is the same as Result::Ok. Of course, you miss out on monadic properties, but after extensively using the language, that's a feature 99% of the time. I would say give it a shot; I was skeptical at first, but this is surprisingly not an issue IMO.

The real issues (IMO) with Go error handling are the clunky `errors.Is()` and `errors.As()` functions for catching specific error values and types respectively as well as annotating errors to get the requisite context (this may already have a solution which just hasn't yet become idiomatic across the ecosystem). In the meanwhile, I just wrap errors with extra context which isn't super satisfying but largely does the trick, e.g., `return fmt.Errorf("writing to database: %w", err)`. Rust seems to have similar problems with respect to different patterns and libraries for error handling, despite having a standard Result type.

Post reply on HN