Hacker News new | ask | show | jobs
by meowface 4242 days ago
Going by Paul Graham's "Blub" essay (http://www.paulgraham.com/avg.html), I'd say the problem is that languages like Go and Java are simply not high in the rankings when it comes to power.
2 comments

The underlying assumption is that the problem that modern programming languages should solve is lack of power. But I don't see that problem in modern codebases. In my experience, the problem is complexity.
I think in this case more power might be a good proxy for less complexity: power should correlate positively with expressiveness, and expressiveness should correlate negatively with complexity. More expressiveness lets you build more powerful abstractions with less code.
> expressiveness should correlate negatively with complexity

I don't see why that would be true. In my experience, the most expressive languages often produce the most impenetrable spaghetti code. Can you explain your reasoning?

Consider e.g. traverse, which is a function you simply can't write in a language without higher-kinded types. Several times I've written half a page of code only to realize "that's just traverse" or "that's just foldMap" or so on. In a less expressive language I would've had to leave that half-page as is. Surely that means the expressiveness results in more readable, less complex code?
Sounds more like boilerplate or redundancy to me than complexity. Things I would call "complex" in a software system are god objects, APIs with too many options, invisible interactions between parts that appear unrelated, and so on.
Fair enough. In that case I'd say expressive languages help, but only indirectly, because they make it possible to keep track of effects and interactions without having to write reams of code.

In a language with lenses, you can delimit where your models are mutated. In a language that lets you treat composable effects in a generic way, you can e.g. split up your variables explicitly with ReaderWriterState, making it clearer which serves which purpose.

The kind of things you might be tempted to use "magic" or global variables for in a lesser language - the "cross-cutting concerns" - you can instead handle in normal code as a generic kind of context. E.g. an audit trail can just be Writer. Or actions that need access to a database session can just be another kind of context. I'm working on such a thing right now (see tpolecat's doobie for a public example of the same kind of thing) - whether a function accesses the database or not is visible right in its type, but it's easy to compose functions that do. The types ripple up, and in the end I'm probably going to do session-creation-in-view - but in a principled way, using the ordinary type system, visible in the code - with Spray, my web route definitions are just another ordinary bit of Scala code (whereas in most languages I would define routes in an external config file, or at best a config object a la Django - adding complexity).

Heck, error handling is a perfectly good example of this. In a less expressive language, the only way around the boilerplate of handling errors where they occur is unchecked exceptions (or effectively-unchecked exceptions, as in "throws Exception"). In a language with good generic context support, the possibility of failure is just another kind of context that we compose with the same generic tools as any other, and the control flow becomes something sensible again.

your "should" and "should" should be replaced with "doesn't" and "doesn't" or at best "may" and "may".

more code has been written in Go than Haskell, Rust and Ocaml combined.

More code will be written in COBOL this year alone than has ever been written in Go.
So what? More code has been written in C and Java than Go and Rust and Ocaml and whatever-else combined. A language's popularity says little about its complexity or how good of a language it is.

Powerful languages let you grapple with problems, weak languages first make you grapple with the language before tackling problems. Some people feel like Go gets in the way. I have not written any Go, but I understand both the praise and the criticism.

Powerful languages can cause other issues, but they do enable certain things that weaker languages simply never can.

You're being a little vague. Can you give a couple examples where software projects were done in "powerful languages?" I can certainly appreciate that higher level languages are better. However, it seems like in practice they are not used as often as you would hope.
C and Java are not the subject here.
Do you have a source? I don't find your claim implausible, however I would like to know how you came to that conclusion.
the internet is my source.
The Internet, in general, can be very unreliable.
> more code has been written in Go than Haskell, Rust and Ocaml combined.

[Citation needed]

> In my experience, the problem is complexity.

Simple languages led to complex code bases.

Many of the Enterprise Java sins were caused by the language limitations and developers trying to work around them.

I think the enterprise Java sins were caused by cargo cult programming. Java can actually be pretty nice when wielded by someone who isn't afraid to invent new things.
What leads you to believe the same won't happen to Go?

I have seen this happen in C codebases before Java took the enterprise.

Its own little macro based DSL and pointers that were actually handles for the real data.

Java's sin is a fetish for over abstraction. Go has a strong cultural emphasis on avoiding unnecessary abstraction.
Enterprise architecture is traversal to the languages being used.
True, but in a lot of enterprise situations the complexity is intractable - it is caused by business requirements.
Exactly because of that I rather use languages that provide the tools to work with complexity, instead of shunning it into the shoulders of developers.

Anyway Go has its use cases, and it is already an improvement if less C code gets written.

The problem with the Blub essay is precisely the assumption that all languages can be ranked on a one-dimensional axis called "power". That assumption is false. (I know this is heresy to say on HN, but in this essay, PG is simply wrong.)

I'm repeating myself here, but: A Haskell user and a Lisp user are both sure that they're at the top of the power curve, and they're both sure that they're looking down when they're looking at the other language, and they can both tell you precisely why they're sure they're looking down ("It doesn't even have a decent type system" and "It doesn't even have macros", respectively). But they can't both be looking down. What's wrong here?

What's wrong is the assumption that all languages can be ranked by a one-dimensional attribute called "power".

Or look at it another way: Power? Power for what? Well, for writing programs. But what kind of programs? General programs? I've never written a general program in my life; I've only written specific ones. Then "power" is whatever's going to make it easier to write the program I need to write. Whatever language does that is the "most powerful" language for the problem I'm facing.

What power is Go shooting for? It's the power to write a ten-million-line application and have it be maintainable for two or three decades. (That's not my guess; it's what Rob Pike said the language goals are.) If you face that kind of problem, Go may in fact be a very powerful language.