Go also made the fantastic decision to design in concurrency as a primitive... And then kinda for on the hill of generics. There's a lot to be said for choosing the right set of features, keeping the code readable as a first priority, and letting libraries handle the rest... Need a lathe? Import lathe!
There's nothing to add for what its creators stated: Go is meant for under-average programmers, not for professional software developers.
It depends on what benefits those language features have. More often than not, they do not provide benefit to your business.
Plenty of professional systems are built in Go. This opinion that Go developers are subpar is silly rhetoric. It is not meant for everything, but for distributed systems it is great.
I don't think so. But it's a fact that Go was meant for sub-par programmers.
Seeing the kind of usage go is known to have inside Google, and how is generally accepted that Google hires only the best engineers, this fails to be consistent. I doubt it very much that anyone involved in Go development has said anything that can be interpreted anywhere close to what you said.
Also, to continue being pedantic I must say that by definition every programmer that gets paid for their work is a "professional software developer" despite the hyperboles grandparent seems to be fond of.
I think this is equivalent to the "spherical cow" problem in physics. A lot of calculations in physics are much simpler, if you assume everything is a spherical cow. However, the real world is messy, and not everything is a spherical cow.
In programming, a lot of complexity comes from interfacing to the real world. Whether it is CPU performance/memory hierarchy, or messy business logic.
The drive for simplicity, often ends up sweeping these under the rug.
it is an optimization problem, and the optimum isn't at the extremum of the constraints, it is somewhere in the middle.
just because C++ is a bit of a mess after 37 years of evolution doesn't mean that the simplest language is best.
rust is also the first widely used language with a borrow checker and may suffer from having to discover the correct primitives while hunting around in the dark to begin with.
Rust is the first widely used language that addresses the question, how do you have memory safety without garbage collection and loss of efficiency. It comes up with (IMO) a very good answer, but likely not the final answer to this question.
But I think trying to answer that question, more than justifies the complexity.
I pretty much agree with everything you said, and think it's a good analogy, but eventually come back to the point of the article we're responding to, which is that a lot of the complicated syntax, and features that languages introduce, just ends up non-essential complexity around the inherent complexity of the real world, that you're highlighting.
Most of the complexity should be in the libraries. Only a small set of select people can modify the core language. Anyone can make a library.
The C language is a relatively small language, but has been used to write complex databases and operating systems. So is C simple or complex? Or both? (Everyone has a different opinion).
Also, there's also a distinction from the small language core (the syntax and lanuage features) and the much bigger standard library that provides additional functionality.
So you can't abstract over data types in C? I often do. Some random thing I often do:
void linear_allocate(Linear_Allocator *alloc, size_t size, size_t align, size_t count);
#define linear_allocate_type(alloc, type, count) ((type *) (linear_allocate((alloc), sizeof (type), alignof (type), (count))))
(Anybody objecting they don't like macros and this is not a real abstraction: You are all fools. To a certain point, that is - before you possibly start being right. But don't underestimate how far this can go, and how long this can be a superior solution over alternatives.)You know something that is very hard to abstract over? Programming language FEATURES! Anybody, please show me the ways of doing computation over all the data that was encoded as fancy programming language syntax. This requires even more language features to get this data back from the compiler in some weird form... if possible at all.
Happily! https://lisp-lang.org/
At risk of stereotyping myself, if you like this kind of thing, check out SICP. It is a really good dive into exactly how far you can go with this kind of tool, and also has applicability across the engineering discipline (not just for lisp folks).
Representing code as data is not very interesting IMO. Code is code, data is data. Granted both are stored in RAM, but they are very different beasts considering how they flow through the machine. Almost any language allows to parameterize over functions (e.g. function pointers), but there is no need to make closures a first class citizen. After all, closures are a brutal abstraction, isolating any context from the caller. When overdone this ends up in a terrible mess where you don't know what's happening anymore (otherwise known as callback hell). Conclusion, use this only as a last resort.
I think there are two different definitions of simple in programming languages: simple to implement and simple to use. Simple to use programming languages can be quite complex under the hood. Python’s bigints are an example of a relatively complex to implement feature that simplifies life for developers.
Whether language features and restrictions simplify life for developers depends on what programs they want to write, though. If you want to emulate wrap-around 32-bit unsigned integers, for example, that’s harder in python than in C.
So, whether a language is simple to use will depend on what programs developers want to write in it. Consequently, language designers should know their audience when designing a language.
You can have a conceptually simple language, but include a massive standard library with everything most users would need.
In a wood shop, you can do everything with a hammer and chisel. You can make a table leg with them. It'll take a long time and won't be super round. However, having a lathe makes it much faster and gives you a better end result.
Also, it's been said that design patterns are just ways around missing language features. What one person considers language complexity, another seems as an essential abstraction.