Live data from Hacker News

Notes on the Go translation of Reposurgeon (2020)

gitlab.com

81–90 of 155 posts

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

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

Builders aren't a good pattern in Go, because it's difficult to express continuations, and they leave types in incomplete states. It's almost always better to use config structs.

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

#82
post #57

Earlier quoted context omitted.

> I think Go people are allergic to writing code that does anything other than functionally work. I think that's what Go was designed for, as a language. To be readable, usable. It's uncaring for your personal programming philosophies. I think that's why it's been successful.

Specifically, Go was designed to be effectively and safely writeable and readable by mediocre programmers.

Mediocre programmers can still write bad Go code. Their code is neither safe or readable.

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

#83

What I really missed was generic map-function-over-slice, which could be handled by adding a much narrower feature. If one graded possible Go point extensions by a figure of merit in which the numerator is "how much Python expressiveness this keeps" and the denominator is "how simple and self-contained the Go feature would be", I think this one would be top of list. So: map as a functional builtin takes two arguments…

ESR's proposal here is basically just another way of spelling Python list comprehensions or Perl 5 map (which is likewise a builtin, with special parsing rules). It's not "new PL territory" by any means.

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

#84

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.

Not everyone is a Kingdom of Nouns purist. Even most OOP proponents that I've spoken with reject Kingdom of Nouns because it's pretty indefensible (in the worst case it leads to banana-gorilla-jungle problems[0] and in the best case it imposes arbitrary and unnatural restrictions on program design). Note also that "modern Java" and "modern C#" and "modern C++" and "modern Python" virtually all reject these kinds of designs and end up looking a lot more like Go with respect to their use of structs/classes.

[0]: https://www.johndcook.com/blog/2011/07/19/you-wanted-banana/

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

#85

What I really missed was generic map-function-over-slice, which could be handled by adding a much narrower feature. If one graded possible Go point extensions by a figure of merit in which the numerator is "how much Python expressiveness this keeps" and the denominator is "how simple and self-contained the Go feature would be", I think this one would be top of list. So: map as a functional builtin takes two arguments…

I also came from Python (15 years of experience) to Go and I think newcomers to Go index too hard on terseness. The for-loop equivalent for a map over a list is more characters, but it's really straightforward and easily recognizable in the code. In the general case, I'm glad that Go doesn't try to explore new PL territory, optimizing instead for things that are known to improve developer productivity. None of this i…

For me, it's not a question of terseness -- it's more about communicating intent, and not polluting the scope with incidental variables. Everyone knows what map/filter/reduce do. When reading new code, seeing "map" is better than seeing a for loop: you don't have to think about the underlying iteration at all, you can skip directly to the essence of the transformation. As a side effect of this, when you do see a for loop, you can safely assume that something about the iteration is non-trivial: maybe the loop exits early, for example. I wrote a bit more about this here: https://twitter.com/lukechampine/status/1463715093733122054

btw, by "new PL territory" I mean "reifying a small set of container operations, without supporting user-defined generics," which to my knowledge is not a position taken by any mainstream language.

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

#86

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…

Go, OCaml and Lisp (depending on the Lisp) all have one other thing in common.. a fast compile/feedback loop. Rust doesn't have a good story here. This would be my guess as to why (at least in part). Particularly coming from a dynamic languages which have super fast compile times if they compile at all.

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

#87
post #46

Earlier quoted context omitted.

> 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 st…

> 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.

In a fine-grained ecosystem, the problem is transitive. You aren't just picking one from 20+ for each of your direct dependencies, you are also trusting that they in turn did just as much diligence as you did in picking their direct dependencies and so on. Curation and pruning would at least help mitigate the scope of the problem.

> ... or write the 24th crate myself.

This is a good example of the xkcd joke about standards proliferation. If I found myself in this situation, I'd prefer to keep the 24th private to my own package. DRY has its limits. Sometimes you've just got to specialize.

I'm aware of the irony in saying this in the context of mmap. But in this case, a thin wrapper that reflects the system call's semantics ought to be available in a common `posix` crate that others may freely rely upon to build their higher-level services. There's no good reason for e.g. ripgrep to have to pick and choose among a dozen flowers for it.

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

#88

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.

Not everyone is a Kingdom of Nouns purist. Even most OOP proponents that I've spoken with reject Kingdom of Nouns because it's pretty indefensible (in the worst case it leads to banana-gorilla-jungle problems[0] and in the best case it imposes arbitrary and unnatural restrictions on program design). Note also that "modern Java" and "modern C#" and "modern C++" and "modern Python" virtually all reject these kinds of d…

Even if you're not doing OOP you're modeling your domain in one way or another. Whether those models are explicit and expressive or not, and how you define those qualities, is another question. In neither case are the arguments to a particular function typically a concept in your domain

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

#89

Personally, I would have gone with Kotlin for a translation like this. It's a closer match to Python than Go, and I think his rule swarm [1] approach to semi-automated translation would have been effective. But then, he might not have liked the fact that, like Python 3 and unlike Go, the Java platform treats strings (particularly filenames) as a sequence of Unicode code points rather than bytes. [1]: http://esr.ibibl…

Go treats strings as a sequence of unicode code points.

I believe they’re treated as byte sequences: https://go.dev/ref/spec#String_types

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

#90

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.

> structs should signal intent Isn't a collection of parameters to a function an intent?

Not really? I suppose what I meant by that was that, if you make a struct, it should represent a concept that makes sense outside of the context of passing it to one function in particular; you're signalling that this collection of data represents a concept in your program
Post reply on HN