It's sort of another worse-is-better dichotomy.
It's sort of another worse-is-better dichotomy.
As you gain experience in Go, you learn idiomatic ways to do things and memorize the core library, but the fundamental mechanics don't change.
As you gain experience in Python, you develop a preference for virtualenvwrapper and experiment with 300 different ways to build a distributable package, then start extending __getitem__ and __setitem__ and adding decorators to everything and before you realize what you've done, you've torn apart the laws of physics and your code has nightmarish side effects lurking around every corner.
Alternatively, you glimpse the chthonic horrors lurking at the end of that path, purge your code of hidden mutable state, and use Python to write straightforward procedural programs.
The move from C++ -> Java -> Go is a perfect example of this cycle.
C++ is a language designed to enable more communication between the compiler and the programmer.
Go is a language designed to enable more efficient communication between programmers.
C was hardly efficient in the 80s micro-computers, and outside Bell Labs people were doing compiler optimization research in languages like PL.8 and similar.
Had Bell Labs been allowed to sell UNIX and history would certainly looked much different.
For instance, Fortran is very performant in numerical computing, even outperforming C, but it has difficulty in accessing I/O mapped registers or implementing an interrupt handler, a jump table, or just cleaning a particular chunk of memory addresses.
"Oh, it was quite a while ago. I kind of stopped when C came out. That was a big blow. We were making so much good progress on optimizations and transformations. We were getting rid of just one nice problem after another. When C came out, at one of the SIGPLAN compiler conferences, there was a debate between Steve Johnson from Bell Labs, who was supporting C, and one of our people, Bill Harrison, who was working on a project that I had at that time supporting automatic optimization...The nubbin of the debate was Steve's defense of not having to build optimizers anymore because the programmer would take care of it. That it was really a programmer's issue.... Seibel: Do you think C is a reasonable language if they had restricted its use to operating-system kernels? Allen: Oh, yeah. That would have been fine. And, in fact, you need to have something like that, something where experts can really fine-tune without big bottlenecks because those are key problems to solve. By 1960, we had a long list of amazing languages: Lisp, APL, Fortran, COBOL, Algol 60. These are higher-level than C. We have seriously regressed, since C developed. C has destroyed our ability to advance the state of the art in automatic optimization, automatic parallelization, automatic mapping of a high-level language to the machine. This is one of the reasons compilers are ... basically not taught much anymore in the colleges and universities."
-- Fran Allen interview, Excerpted from: Peter Seibel. Coders at Work: Reflections on the Craft of Programming
The reason why older languages are complex and inelegant is because our understanding of how to create simple yet useful languages has increased, not because older languages accumulate much complexity.
One of the big differences is that Java and Go have straightforward context-free grammars, mostly, and you can whip up a working parser in no time. C++ is a bit of a beast, by comparison (hence keywords like “typename”).
C++ also has the complex overloads and template system. I think people underestimate how complex these things are when they are learning C++, and how complex their interactions are. Then there’s the preprocessor.
You can kind of argue that these are just an accumulation of changes, but other languages contemporary with C and C++ do not suffer from these complexities, so the argument falls flat. By comparison, Go and Java rely on reflection or code generation more, and these are a bit simpler.
And then there is arcane stuff like this:
* https://en.cppreference.com/w/cpp/language/eval_order
* https://en.cppreference.com/w/cpp/language/copy_elision
That does make the language feel very complex even without the whole templates depth.
https://www.youtube.com/watch?v=_ahvzDzKdB0
or as PDF:
https://www.cs.virginia.edu/~evans/cs655/readings/steele.pdf
> We need to put tools for language growth in the hands of the users.
Guy's previos work with Common Lisp is epitome of this. There are three kind of macros in the language: reader macros, macros and compiler macros. They give the tools for the user to extend the language. There is just 25 or so core primitives in the 'core' language and the runtime. The rest 900+ functions and symbols are basically the standard library (the fact that they are slapped into the same package and they extend the core in a ways that other languages can't hides the simplicity of the language somewhat).
The creator has repeated this philosophy a few times:
> There is very little reason for an Elixir v2.0 with breaking changes. The language was designed to be extensible and if we need to do major changes to the language to improve the language itself, then we failed at the foundation.
https://elixirforum.com/t/what-would-you-like-to-see-in-elix...
> A big language does not only fragment the community and makes it harder to learn but it is also harder to maintain. It is also why the language was designed to be extensible: so the community could build what is necessary without a push to make everything part of the language.
https://elixirforum.com/t/questions-about-property-testing-s...
> We also understand there is a limited amount of features we can add to the language before making the journey too long or the language too big. Adding something now means not including something else later. As an exercise, let’s see a counter example of when we didn’t add something to the language: GenStage. [...]
https://elixirforum.com/t/questions-about-property-testing-s...
It is like designing a workshop. You only have so much space within arms reach. Here you place your most frequently used and valuable tools. You can "grow your language" by adding tools but they can't replace what you have in this limited and privileged position - instead, new tools have to go in cupboards or on another table. The new tools will have higher friction than the first priority tools you added.
Maybe you can have a workshop where you imagine a tool and it appears in your hand thereby removing the constraint of "tools within reach" but I think this then makes it too ephemeral and abstract. It is the constraints that makes a language tactile and ergonomic - remove the constraints and you have no structure at all.
In this case, the "tools within reach" are your core keywords and syntax. Growing features via libraries or syntactic extensions generally incur more ceremony and less elegance. Having totally flexible syntax extensions/keywords doesn't solve the problem, it just moves up a level abstraction/generality and means you have given your users the "design a language" problem instead of solving it for them.
This is an interesting observation that reminds me of
> In Lisp, you don't just write your program down toward the language, you also build the language up toward your program.
from Paul Graham's "Programming Bottom-Up". Some people would consider it an advantage being allowed to fold the "design a language problem" into the overall problem.
More, I think this is just a matter of degree, not kind.
As soon as you have something as apparently simple as named procedures, you're really writing a DSL, albeit very coarsely, for your business problem. Add named record types. Add textual macros. Add operator overloading. Add Lisp-style macros. At every point where the language allows a word on the screen to stand in for something larger, you're giving the programmer the power to design a language for their problem domain.
C++ were very performant, and unlike Java not a memory hog, but for this sort of tasks it was deemed to complex. Besides the ammount of people that were able to program in it was limited (and you can even see this reasoning being used as a reason why they created Go).
Then Go showed up with simplicity and a good story in performance and memory, deploying simple binaries in a world of complex server infrastructure paved out by Java was a very handy and right on time approach.
The problem with Rust now, is that it is target the system programming, in a era of system programming renaissance given the whole mobile app scenery.
The problem is; there is already a lot of C++, C, Java, Objective C and Swift code there, so it will be hard to have a good reason to rewrite complex stuff with a lot of man hours in it in Rust.
Every language needs a platform. C is here because of Unix, C++ because of Unix, games and early 2000 and 90's era startups. Java and C# because of bussiness software, Go because of the cloud, Ruby and PHP; because of webservers, Rails an blogs, Python for educational purposes, Data Science, ML and now AI.
Now what about Rust? Its trying to eat some lunch from C and C++. But a lot of code and value is already there in C and C++, where rewriting it in Rust just for some ocasional added value here and there is not reasonable.
Its really tough, and if Rust dont find a platform to grow it will be very hard to advance any further. But, there's always new tech waves and tools that will marry perfectly with them.
Lets see which languages are able to be a perfect fit for them in years to come. But right now Rust will depend a lot of the community it already formed to keep sharp and maybe be lucky to surf one of those waves.
For existing software it certainly is less about rewriting it but extending it in Rust.
Thanks to not having a runtime and being quite easy to create a shared library with a C-ABI, pretty much any software written in any language could be extended with code written in Rust.
Ok, but you kind of added complexity to your codebase. Now you will need not only C++ coders, but also Rust coders. If you are Mozilla or Google you can do that, you eat complexity for breakfast.. But they are probably not the companies you need right now to keep your steady growth, unless of course you are lucky that they created some killer app in Rust because of their in-house use of it. Like Google did recently with Kubernetes, only it is in Go of course, but i guess it checks the square of a killer app which helps into the language adoption as a programming trend.
Speaking of Go, it once was suffering from the same problem Rust is going through right now. It was sucessful in a first phase because of its community, but it needed more to start having more adoption and mind share. Then, Docker happened, and Go found a sweet spot to aim for and take it to the second base.
Another platform is cryptocurrencies/blockchains- Rust lends itself uniquely as a modern C++ for writing performant blockchain protocols. This is evidenced by the Parity team using Rust exclusively for all their projects. As that world evolves Rust can find a foothold there as well - there is no real legacy code floating around, the Bitcoin protocol is only 10 years old.
The blockchain trend reminds me that Rust could also try to find some cosy home in banking software, in expert systems and in embedded software.
The key now is to be humble and not to try to pick up a fight with C and C++ just yet.
Go only now is in a position to pick a fight against Java in the server and in the cloud, and Rust will probably need to get into the same point of adoption, if it wants to be seen as a serious contender to those languages in the eyes of the people they need to convince.
Unfortunatelly Rust missed a good new trend now, with multi-platform cores for mobile phones that ended up being written mostly in C++.
Rust wasnt even invented when people were trying to solve the problem of multi-os phone apps.
And that is the current trend which is giving the system development trend a second chance. But is not that bad, because thats exactly what is making people to take a serious look at Rust.
Battery life, memory, storage. It all matters again thanks to the phone environments, and you cant afford the be wrapped in layers upon layers of software virtualization like it was common in the early PC era, where Java and C# were kings.