Hacker News new | ask | show | jobs
by imiric 1039 days ago
It's not about purity or dogma. It's about keeping complexity out of the language as much as possible, which is much harder to do. Language designers always make a tradeoff between making programming tasks convenient, and introducing more complexity that makes the language more difficult to maintain and less approachable, and programs written in it more difficult to read and reason about.

Being productive in a language is not just about using every convenience at your disposal, and typing less. It's about producing code that is easy to read and approachable for others or yourself years down the line. The more language features one needs to be aware of when writing or reading code, the less approachable it is.

Having less features also forces the programmer to rethink their solution in a less clever way. In dynamic languages like Python and Ruby it's very convenient to use some fancy trick to write less code. In languages like Rust or Raku, you can (ab)use some obscure feature in a non-intuitive way, and feel good about the "elegance" of the solution, but a fresh pair of eyes might struggle to understand what the code actually does. Considering reading code is much more important than writing it, as we literally write code for humans, not machines, optimizing for simplicity and having less features in a language is a more productive long-term approach.

3 comments

> It's not about purity or dogma. It's about keeping complexity out of the language as much as possible, which is much harder to do. Language designers always make a tradeoff between making programming tasks convenient, and introducing more complexity that makes the language more difficult to maintain and less approachable, and programs written in it more difficult to read and reason about.

Complexity is not something you can remove.

Complexity removed from language moves to the application.

The best thing you can do in the language is to make expressing complex concepts in easier, more clear way. Going too simple just produces more boilerplate and makes it harder to read.

Keeping complexity out of the language does not remove the complexity. It moves it into the programs. MIPS assembly is a very simple language with specs fitting on 10 pages. Yet you probably wouldn't want to write a web application in it. Brainfuck is even simpler as a language, but the programs are even harder to understand.
sometimes it moves the complexity up the developer's head : "are you sure you really need to do all this, and there isn't a conceptually simpler solution to your specific problem ? Think again !"

That's the real value of "simple" languages like go.

“Am I really sure I want to loop over batches instead of fetching one record at a time (or the whole set of results at once)? Ugh, it’s a complete pain in the ass though, one at a time it is.”

You literally don’t have to use iterators if you don’t need them. You can just range over a collection as you do already. But when you want something a bit more performant like looping individually over batches or generating an enormous sequence of records on the fly, they make what would either be tedious or difficult into something trivial.

Go being “simple” just makes application code unnecessarily verbose and makes dealing with even moderately complicated problem domains feel like solving novel computer science problems when it’s be four lines of boring code in better languages.

Aren't we talking about standardizing iterators? That makes the compiler slightly more complex, I guess, but for the language it makes it much easier to read and more approachable imo. That's the reason that range exists in the first place.

I don't see why the author's implimentation is so complicated. I really just want an interface that works with the range operator, and to call it a day.

    type Iterable[T any] interface {
        Next() (T, bool)
    }
so that

    for _, el := range someIterable {
    }
is essentially the same as

    for el, ok := someIterable.Next(); ok; el, ok := someIterable.Next() {
    }
I certainly think the first is more clear btw.