Note: Rust actually has a chance because it's simple compared to its competition: modern C++.
Note: Rust actually has a chance because it's simple compared to its competition: modern C++.
Of course, you pay the tax somewhere else and that is code duplication. You see this in Go due to the lack of generics, which often results in duplication of code for different types or reliance on reflection (which is slower and can lead to runtime errors).
This is not a critique of Go, just to point out that it is a trade-off, and there isn't necessarily one right answer.
Don't get me wrong, I like generics. I think they would be a nice addition to Go. But I understand Go designers when they try to be conservative about it. I like that they only add features when it's absolutely obvious that the pros overcome the cons.
For you...
It depends on what kind of code you are working on. If you work a lot on numeric code (e.g. in machine learning), you want to make it easy to specialize on e.g. 32-bit or 64-bit floats.
Also, since only built-in types are generic, you cannot implement other containers (you never need binary search trees?) in a safe manner.
So, yes, the lack of generics is a frequent issue for me.
I only point this out because I've seen a lot of Go programmers defend Go by saying parametric polymorphism is only really important in particular niche domains, when really they want to say that Go only focuses on a particular niche domain where it isn't important.
The point I am trying to make is that adding some features from other languages doesn't provide sufficient value without also adding other features. Adding all of them can make the language significantly more complex that you wonder whether the benefits gained are worth it.
Since proper error-checking in Go actually requires doing by hand what a pattern match would have done anyway you're not simplifying anything for anyone by omitting them; you're just making it harder for the compiler to provide compile-time checks.
A pattern match is basically a switch statement. Go already provides the latter so the language would not need to become more complicated.
It's fine for languages to embrace those features, and be what they are, and it's fine for Go to reject those features, and be what it is. We don't need "one language to rule them all".
Lisp is a very simple language conceptually. The problem is that it allows you to build insane amounts of complexity in a very "free for all" way. No "one sane default way to do it".
The problem is now how complex a language is, but how much needless complexity it allows you to build yourself.
Go seems great because it doesn't easily allow you to build needless complexity. Though I've never coded anything meaningful in it, so my praise for it would be armchair thinking...
For myself, I still like it, a lot. To the point that the more I learn of it, the more I'm confused on how it hasn't taken off better.
Most of it are not primitives though, Common Lisp only defines 25 special forms. Guess how many keywords Go has?
For example Common Lisp provides support for complex numbers and operations for them. These operations are 'primitives' in the language. This is unrelated to 'special forms'.
Any Turing-compelete language allows you to build arbitrarily much needless complexity. I don't see how it's a useful metric at all, except to say, "Well, this language isn't quite so horribly stunted that you can't even produce a nonterminating program."
If you want to talk about how easy it is to build needless complexity— well, I've yet to see a programming language that knows the difference between necessary complexity and needless complexity well enough to allow the former and prevent the latter. Rather, languages either let you build complex things easily, whether you need that complexity or not, or they just make it a right pain in the ass to accomplish anything.
Personally, I prefer the languages that let me express the complexity of my problem domain easily; sure, I could use them to make things more complex than they need to be, but I don't, because to be quite frank that's just part of being a competent programmer.
> Every single abstraction has a price in complexity.
I think the whole point of abstraction is to lessen complexity; wrap up many different things into one thing that's easy to reason about. Very few languages support creating good abstractions, unfortunately.
Abstraction lessens complexity, and also adds complexity.
Take monads in Haskell, for instance. Let's oversimplify and say that absolutely everything is done through monads. Great; we've now wrapped up many different things into one thing that's easy to reason about. And when I want to do something, I don't have to think at all - I just reach for a monad.
And then I have to think, because now I have to figure out how to make a monad do the specific thing that I actually want it to do.
Or I'm reading the code, and yes, that's a monad, because it always is, because everything's done through monads. But what is this monad at this location in the code actually doing? Well, I have to work my way back out of abstraction to concrete in order to understand that.
One way to think about this is abstract art. As art gets more and more abstract, at first I can't tell whether I'm looking at a blonde or a brunette. Then I can't tell whether I'm looking at a male or a female. Then I can't tell whether I'm looking at a human or a chair. And finally, I get to the point where I'm looking at a painting that could be anything, but it's impossible to say what it is. Abstraction has proceeded to the point that communication (between the artist and the viewer) has been lost. In the same way, abstraction in code can proceed to the point where communication between the author and reader is lost, and then it takes a lot of work to wade through the layers of abstraction to find out what the code is actually doing.
When someone talks about a language, I'd rather they talk about what exactly it is the language simplified and where it hid the rest of the complexity. One can only simplify a Turing Complete language so much before the it starts running up against the limits of Kolmogorov Complexity. After that point, the best we can do is shuffle it around - under the bed, or under the sofa, or inside the closet, or into a corner - depending on each programmer's preferences.
When people talk about abstraction for example, they really mean reducing mental complexity. The pro is that we can reason about a larger percentage of our programs by being able to fit more code into our limited working memory. The con is that something other than our brain (e.g. algorithm w) has to do the heavy lifting. With abstraction, all the little details (the complexity) still exist somewhere, we just don't have to look at most of them.
But most of the time, we are abstracting away something specific in order to make something else more concrete and less obscured by irrelevant detail, hence reducing complexity.
Of course abstraction can go wrong, because sometimes we abstract away things that are very relevant, perhaps in futile pursuit of future code reuse. But having the tools for abstraction does not make abstraction go wrong. We do.
The marketting muscle that was put behind Java certainly helped it in its time. Same for the actual market that backs objective c.
C probably benefited as much from the open distribution as it did anything else. Combined with a relatively high quality compiler that was heavily distributed (gcc), this can not be understated. The only languages that were as highly distributed were probably the various BASICs, and there are obvious reasons to fall off of those at some point.
So, you can blame lisp's lack of popularity on its complexity. I am not so sure that is a good foundation, though. I feel it is as much lack of a high quality distribution of it as it is anything else.
Though, highly on topic, it should probably be noted that the approachability of the original C Programming Language book that is making so many people excited about this book probably had a very heavy influence, as well. I am not so sure a book can have as heavy of an influence in today's environment, but I think it would be foolish to discount the amount of influence a publication like this could have had back in the day.
GCC certainly contributed to C continuing to be widely used.
That said, you are definitely correct in C's early popularity. And that probably contributes more heavily than later items. (There is a term for this, but I can't remember it right off.)
Before UNIX became part of the enterprise workforce very few cared about C.