One language is better. It is just better to learn one language rather than learn C++, Python, C#, etc.
Just build one language that makes you build apps, websites, games, AIs, etc.
One language is better. It is just better to learn one language rather than learn C++, Python, C#, etc.
Just build one language that makes you build apps, websites, games, AIs, etc.
In theory, you only need one language and, provided that it is Turing Complete, any language will do. But...
"In theory, theory is the same as practice, but not in practice." (Often attributed to Yogi Berra).
If you only ever want to learn one language, it should probably be C, though C has a number of twists and turns that make it difficult to consistently produce error-free software. It is, however, a low (close to the hardware) enough language that you can do anything you like.
However....
If you program in a low level language for a long time, or if many people do so, then what you find is that the same sorts of things are being written over and over again and debugged over and over again. This is undesirable, so the practitioners will build libraries that capture things frequently done. But hundreds and hundreds of libraries have their own problems; among them, just finding what you need.
So...
People decide that it would be an advantage to "capture" the commonly done things as "abstractions" in a new language built on top of the old.
In FORTRAN, for example, there were functions that captured commonly needed actions (trig functions, for example). FORTRAN was built on top of machine language, as was C, which also uses functions as its main abstraction mechanism.
And then...
Programmers decide that the actual structure of a program is looking a lot like the structure of some other program and so, just maybe, those structures can be captured as language "features", leading to the writing of new languages.
Now it starts to get interesting.
Some folks have the insight that mutability of data isn't really essential to (most) computation and that programs compute values, possibly complex. So a new language, say LISP, is created to capture this insight and it proves fruitful.
Other folks find themselves doing a lot of modeling of things and so they ask whether the properties and actions of those things can be captured directly at the language level, rather than have to be reconstructed from the simplest actions of something like C. That led to both Simula and Smalltalk (which have some conceptual similarities).
Now, and this is the important bit:
A language that does a good job with abstraction will provide to the programmer a complete (in the sense of Turing) and consistent mental model in which to program, making it unnecessary to think about the underlying implementation and even permitting you to forget that there is some machine that a program might manipulate.
Such a language also provides a mental model of the nature of computation. A functional programmer is led/encouraged by the language (perhaps Scheme) to think in a certain way. Object Oriented Language (Smalltalk...) encourage you to think in a different way. Each of those mental models, if complete and consistent can help you formulate and solve programming problems as they arise. These different mental models are called paradigms.
Just as you don't need to understand Sanskrit to understand English, you don't need to understand machine language to understand Scheme or Java. Each of those (among many others) provides a model of computation in which you can describe any computable process in a consistent way. Buried in all of that are the earlier libraries that people used to have to build, along with (big big point) the insights that were gained in earlier programming attempts.
As long as we can envision higher levels of abstraction, there will be an impetus to create computer languages that try to capture those abstractions so that they can be manipulated easily and consistently by working programmers.
And then, programmers who want to be productive, will try to match the language to the task at hand as well as choosing a language that has abstractions appropriate to that task.
For an example of what I mean by capturing abstractions, consider the problem of building dynamic data structures such as binary trees and such. In a language like C or early versions of C++ these are specifically allocated (on the heap) but also need to be specifically deallocated somewhere in the program. The implication is that the memory management "problem" needs to be resolved in every program that uses dynamic allocation. Every program. In a language like Scheme or Java, on the other hand, there is a garbage collector that assure that deallocation is done correctly. The garbage collector needs to be verified only once, not redesigned and re-validated for every program. This frees the program to put their mental energy elsewhere.
I once (unintentionally) put a deallocation bug in a C++ program. The correction took me 24 hours to find. The solution required a one character change to the program. One character progress per 24 hours isn't very efficient.
std::vector
for arrays, and they never have memory leaks or deallocation bugs. For students that you would teach in C, modern C++ (meaning 17 and later) is a better language.
$\endgroup$
Commented
Jan 2, 2022 at 20:31
I'm going to echo what Buffy said, but in a different manner.
All of the great languages have a sort of direction that they point in. For instance, the Excel language (yes! The one from the spreadsheets!) is really great at short scripts that manipulate and represent data. By contrast, the C language is excellent at telling hardware what to do, while Mathematica excels at representing a lot of advanced mathematical functionality very simply.
There is nominally no task that you can do in any of those languages that you cannot do in the others. However, you will find it extremely difficult to go against the grain of the language. Want to create a program to rapidly edit and make visualizations of data in C? You can do it, but you could spend years on it and never make it as convenient as Excel. Want to do very small, very fast operations that C makes simple as could be? Excel would rapidly become a nightmare.
The different languages have been created to optimize different kinds of actions, and the great languages each do exceedingly well at what they are designed for.
That's the key to why we need different languages. We need to do different tasks, and we want languages that generally work with us to get us there, and don't actively get in our way all the time.
Imagine you open a carpenter's toolbox and you see
You are incredulous. All three of these things are used for joining two pieces of wood together. Why in the heck would the carpenter carry around three different things that all do the same job? Why would he learn how to use all three tools, when he could learn just one?
Of course, the answer is that some tools are good for some jobs, but bad for others. In some situations, glue works great but nails and screws would not. Other situations, glue is horrible, screws are great, and nails would okay. For some jobs, all three might work equally well.
It's the same with programming languages. For some jobs, this language is great but that language is horrible. For others it is the opposite.
This is a CS variant of the Sapir-Worff hypothesis: your world view is shaped by your language. Different programming languages make you think in different ways, and are suitable for different purposes. In CS terminology, there are different "paradigms". Some languages are imperative, some declarative. There are functional and logic languages. And they all make you think just a little differently.
One language is better.
Sure, and if you ask five people which one language is best, you'll get six answers.
Computer programming is not a solved problem. We're still learning the best ways to do it. Some languages are better suited for certain tasks, but there's also plenty of room for differences of opinion even with a single well-defined problem domain.
The US Department of Defense actually did create and use one programming language for basically all its varied programming tasks for about 10 years. As stated in A programming language developed by the US department of defense was name to honor a famous female mathematician Name this programming language?
Ada is a structured, statically typed, imperative, and object-oriented high-level computer programming language, extended from Pascal and other languages. It was originally designed by a team led by Jean Ichbiah of CII Honeywell Bull under contract to the United States Department of Defense (DoD) from 1977 to 1983 to supersede the hundreds of programming languages then used by the DoD.
Also, U.S. DoD Use of Ada explains
With various exceptions and waivers the U.S. DoD was required to use Ada when it develops its own software. This requirement was often called the "Ada mandate". A summary discussion of the U.S. DoD Ada mandate, as well as related documents, are available. The basic text of the Congressional mandate is:
"Notwithstanding any other provisions of law, where cost effective, all Department of Defense software shall be written in the programming language Ada, in the absence of special exemption by an official designated by the Secretary of Defense."
In the Does the Defense Department still promote the Ada programming language? Quora thread, the answer by Rochus Keller explains that the requirement mentioned above started in $1987$. Also, the answer by Jim Rogers says
A short history of the Ada language mandate is found in Ada Programming Language - AcqNotes. The concluding paragraph indicates that the Ada Mandate was effectively removed in 1997 when the DoD began to embrace Commercial Off The Shelf (COTS) technology.
I've used quite a few different programming languages, but I've never done any programming using Ada, and know relatively little about the language. However, in 1987 (when Ada use was initially mandated) and 1988, I was working for Netron (a Toronto, Ont. company) on a COBOL related project with IBM for Westpac Banking Corporation in Sydney, Australia. I recall a discussion with several programmers (note I'm unsure to what extent any of them had used Ada before) about a major problem with Ada being that it tries to do basically everything, with this making it so large and complicated that it's difficult to learn and use, as well as it not being a particularly good choice for many programming tasks. On the other hand, the Quora thread I mentioned above has several Ada programmers explaining some of Ada's significant strengths.
In conclusion, since the US DoD was unsuccessful (due to both subjective, as well as objective, reasons) in creating and using one language to fulfill almost all of its myriad requirements, I doubt that any entity, public or private, can create just one programming language to be able to do basically everything well.
Really, when making your own language is something people or companies can do, it's almost the default for that to start to occur.
Let's say there was just one language everyone used, or perhaps a couple of them to cover all the different paradigms. Chances are, not everybody's going to like parts of it. Maybe some aspect of the syntax seems weird to some users, or it's not fast enough, or it's not as portable as people wish it was. So, what happens? Someone makes a new one, quite possibly just an incremental improvement on the one they were using before (think C++, Kotlin, or Typescript).
A programming language will never be "one size fits all". People from different backgrounds, like C, Python, or Haskell, will find different syntax more intuitive, and will have different needs and expectations for what a language provides (e.g., garbage collection, first class functions, a large standard library, and so on). The natural result of this is more languages being made.
The Title of your post, and the content are two very different questions!
I want to say initially yes, but ultimately you may need to learn a number of languages in your career if you want to develop on or for the latest hardware and operating systems as they evolve.
The programming language is really just syntax for compiler instructions. After you gain proficiency in a language you will hopefully gain an appreciation and understanding for how that language works, if not why it works. Different languages are written for different compilers, once you understand one language then picking up another language can be much simpler if you understand how the new language syntax structure relates to the language you are proficient in. So once you gain proficiency in one language, transferring to another should be much lower effort.
The counter argument to this is that it takes a lot of practise and therefor a long time to gain proficiency in one language. Instead by learning and using multiple languages at the same time, you can pickup the similarities and differences quicker and may gain a better understanding of computer science concepts in general because you will more practised at differentiating between language and concept.
From a formal education point of view, it becomes practical from a tooling/teaching/resource perspective for institutions to streamline the teaching of many different concepts into using the same language. You want to minimise the time and effort it takes to get your learning and development environments up and running. If you reduce the language and environment options you can reduce the documentation and guidance that you may need to provide but you can also maximise the returns on pre-requisite knowledge across subjects/units.
What is important to the institution is that the language(s) adopted are capable of providing relatable examples to cover key CS concepts and methodologies and that they can find instructors proficient enough to deliver the necessary content. Many of these practical concepts will drive the language selection and therefor the natural bias of that next cohort of students, which can further skew this conversation...
Whilst one perfect language might be a great idea, there are a lot of different competing opinions around what that perfect language might be, Turing Completeness, though well accepted and established, is still just a theory and one of many opinions especially on how to very that the language is complete. ;)
Before we try to create one new and perfect language, we would seek to find a way to incorporate some, if not all of the previous popular algorithms and abstractions that make each of the current languages great. But can such a thing be done, who would be responsible for re-writing the code from existing frameworks and languages, how do we determine which to bring across, who can be trusted to verify the completeness of this language?
There are many general purpose programming languages that have been created in the past, and I'm sure we haven't seen the last of them. Typescript is an interesting example specifically of a higher order language that compiles into a lower order language javascript for execution in web browsers, we will probably see more of this type of evolution in the future because it deosn't require any additional effort from hardware or OS vendors. There are many theoretical benfits that TypeScript offers over javascript, I think we all agree that TypeScript has its place, but in a simple HTML page I can quickly use Javascript to satisfy many requirements it will run effectively natively in the browser without needing further compilation.
What tends to rule the discussion is effort in the form of Time. Time is money, if I can use something to achieve an outcome quicker than other options, then using it might make me more money. So I will consider it.
@Buffy raises some excellently phrased points but we need to recognise that programming languages are bound to commercial interests, whether that be the IDE, a storage or hosting platform or client end runtime framework or platform. As developers we are constantly fighting between what is theoretically "best" and what is a commercially viable or practical language for development for our particular client.
The hardware or environments that code is deployed to can restrict the possible languages which will significantly contribute to the total cost of designing a solution. So regardless of our experience or language proficiency, we may come across a client that whose solution must be deployed to a very specific hardware or medium or that client may have their own
Some hardware vendors have specifically designed their own languages either in an effort to protect their hardware or implementation IP or sometimes hardware/vendor providers are deliberately trying to create separate market verticals, sometimes driven from a greed/commercialisation point of view or sometimes as a deliberate legal avoidance technique.
Java was supposed to be the killer all purpose language, MS Developer Studio and early versions of MS Visual Studio even included support for variants of java (j++, j#). The variations were an evolution of the original java, enhancements to increase developer productivity and in part driven so they could integrate the complied assemblies with Internet Explorer to avoid some trust and operational constraints that were enforced from the official JVM runtime specification.
Even before official complaints, MS were working on C# as a Java replacement that they could support and package directly in their operating system and browser products without being dependant on the language and JVM specification controlled by a competing commercial provider. MS were sued by Sun Microsystems because the MS java implementation was not 100% compatible with the java specification and as part of the settlement java support was dropped before the release of Visual Studio .Net.
To properly answer the why we have multiple general use languages in the first place it might be helpful to talk to someone who has experience authoring multiple languages, Mr. Anders Hejlsberg comes to mind as co-designer to many general purpose languages including Turbo-Pascal which replaced a previous general purpose language Pascal, Delphi and of course more recently C# and TypeScript.
What I appreciate about Hejlsberg's designs is that he does not just focus on the language itself but he strikes a pragmatic balance between all stakeholders including the complier and interpreters. He puts a lot of energy into ensuring the tools, documentation and support libraries are provided and maintained to keep the language commercially viable.
His engineering work is sometimes criticised as being in part derivative of other languages or attempts, but how many of us have truely original thoughts anyway? Hejlsberg applies an iterative approach as he continues to find ways to improve developer productivity.
What is interesting is that changing hardware technologies and costs over the years means that what we want and expect from computers is evolving. As tech evolves some software driven algorithms get packaged into or replaced by hardware implementations, and some hardware implementations become more cost or energy efficient to be implemented in software. This means that the languages need to evolve to cater for these changes, over time you reach a point where there is no easy way to add a new fundamental extension to your language without contradicting, de-stabilising or rewriting all the previous rules and regulations. At that point, the next version, even if it has the same name or similar syntax, is probably a new language of its own.
@
notation) to replace JNI. Sun somehow argued that no-JNI broke "write once, run anywhere". Note, by the time of the settlement, I was fulltime at Microsoft.
$\endgroup$
One more aspect:
Every non-trivial software project uses its own, problem-specific language. So, there's literally millions of programming languages in use.
How that?
Bigger software projects always consist of multiple layers, where the lower-level (library) functions help to make the higher-level ones easier to write and understand.
Designing software in layers effectively means to create (in the lower layer) the vocabulary you want to use in the next-higher layer, thus creating the language you want to use for expressing your solution.
So, in a way, there are no two programs using the same language, as they all introduce lots of problem-specific vocabulary.
With bigger software projects, knowing the base programming language (like C, Python or Java) is by far the less challenging task. Understanding the problem-specific vocabulary (classes, fields, methods, ...) plays a much greater role.
So, why do we still have different base languages? Because we choose a language where the base concepts plus the available libraries provide a reasonably-good match to the problem-domain, so we don't waste precious resources on creating abstractions that would come for free with a different base language.
In many companies you standardize on one or a few languages. This saves a lot of time and effort and basically makes the whole operation more efficient. In the company you can have a "dictator" deciding on how to work (well not actually a dictator, but might be called software architect or similar).
But you cannot order other people or other companies to use the same language. The US military tried with the language Ada, but failed to impose the usage of it on everyone. Ada is sadly just about dead now, sadly because it was/is a really good language and could have replaced all of C, C++, Fortran and Cobol and some other languages as well.
One driving factor for using several languages is what type of program you are writing and where it will run and the restrictions this sets for your choice. For a very common type of application today, a web application, the programming often falls inte three different parts and then three different languages. As example, see a largish web shop (say, www.thomann.de )
Could you even create one language for all different usages? Personally I say no! And even if someone did, a few years down the line people and companies would create and select other languages.
There are a lot of great answers here which explain why it's good that there are so many different programming languages. But that's not exactly what you asked; you want to know why there are so many different programming languages.
I think the answer to that is quite straightforward: programming languages are not actually that hard to create, and when somebody designs a new programming language, they aren't thinking "I want there to be more programming languages", they are usually thinking "I want there to be a language like this". Besides the motivation to design an "ideal" programming language without the drawbacks and blemishes of earlier languages (in the language designer's subjective opinion, which of course differs from every other language designer's subjective opinion), it is actually quite fun to design a programming language.
Sometimes a programming language exists simply because someone had a funny idea for it at the pub. So it would be strange if there weren't thousands of the things out there!
Buffy and Ben offer logical explanations to the plethora of languages that exist. The ideas make sense, you need a better tool, you have a different niche. But languages don't exist solely because they work better than another language for a specific use case. There's a human element in there that makes things a whole lot less fun and a whole lot more arbitrary.
For example, the list of languages Ben had, each are not the ideal language for their own use case, or exist in spite of other languages for not very nice reasons.
Excel's language is not the best for "short scripts" and is severely limiting compared to many dozens of languages, including python. For example, instead of having to execute statements hidden behind visual cells, it might make more sense to have a series of statements that refer to specific cells ie:
suming an entire row.
cell[row][col] = sum(cell[row][:])
or sum an entire square subsection:
cell[row][col] = sum(cell[row_start:row_end][col_start:col_end])
If you want to do something like simple sum rows in a table if they meet a condition, that's near incomprehensible in Excel's programming language:
=SUMPRODUCT((ISNUMBER(FIND(UPPER("("&O$5:O$9&")"),B5)))*I$5:N$9)
So clearly Excel's language is not the easiest or best choice for such a thing.
The real reason Excel's language exists is because it already existed. Here's what I mean. The average users use case of Excel doesn't even include using the programming language directly, much less these summing routines. Using a better language doesn't make a lot of business sense, since it's relatively niche in the first place. What's more, if you change to an objectively better language for the job, you've also alienated your pre-existing customer base, many of which will be angry and stubborn attempting to stick to their inferior product, since they don't want to learn. You may be stuck supporting the "old way" regardless because of stubborn customers.
If we get to C, C doesn't exist because it is the best language for working with low level hardware/telling the hardware what to do. C doesn't even map properly to large swaths of different devices it's used on, it can't encapsulate ideas of paged ram that many pieces of hardware have (where you can't address pieces of memory directly, you must first execute a function to be able to address a place where a piece of memory resides). C often does extra work as well, because it doesn't have many compile time constructs, so you're often doing work at runtime that could be done at compile time, or using another language to generate C code which represents your compile time construct. C++, when you can use it, is objectively a better language for "mapping to hardware", it is a 99.999% superset of C and can do things faster, easier, and less error prone. But languages like Rust, are even better than that, as most functionality and many libraries are still available even after you remove the standard library.
C is used because it already exists, and has a stable ABI. Now that ABI thing might sound like a "neat programming language feature", but really, it's another political thing. ABI, application binary interface, refers to how compiled programs interact with other compiled programs, calling functions from the assembly level in your code. If ABI's aren't stable, new versions of a language or compiler might cause previously working code, that was linked during runtime to another library, to no longer work. An ABI becomes stable when compilers agree not to change it. The only reason C's ABI is stable is people agreed not to change it. It's not because C is an elegantly written language, it's because people used it.
C's niche today is for glue code because of it's ABI stability. Lots of other languages know how to talk with compiled C code because of this. C, because of its ubiquity, and how old it is, is supported by a wide variety of hardware. This makes it convenient when targeting low level code for the widest set of devices, but it isn't a feature of the language that made it so. Often it is used to boostrap OS's and programming languages because of this. Some platforms don't support C++ and rust because no one's bothered to write implimentations for those platforms for those languages. These languages are "more complicated" thus often it means that these other platforms don't want to put in the work to support them. But for C++ and Rust implementations relying on LLVM, or other 3rd party IR tooling, it's not because of the language at all, it's because the vendors don't feel like putting in the support for LLVM targets.
Mathematica is not a nice language to use for most programmers. It's really inefficient and the tooling ecosystem is entirely tied to wolfram products. It's not pleasant to use, and only appears "great" to a mathematician, because mathematicians don't want to learn programming languages, so you have to trick them into using the tools they actually need to use. There are some nice visual features, unrelated to the language itself, but as we see with python notebooks, this can be accomplished in basically any language if someone put forth the effort. So that's not a positive for the language itself. Mathematic symboligy is chronically overloaded to the point where even simple symbols, like the delta, can be confused within the same function for a multitude of different usages. Mathematic symboligy is not efficient for understanding with that respect. Some one wise once said:
"[Mathematic] equations are like code golf you're forced to read".
The purpose of Mathematic symboligy is unfortunately not to for reading, but for easy writing and an "objective" symbolic set across language barriers. These equations are often written write and forget.
Now others might tout mathematica's symbolic math power, and other utilities. The problem with this is that this isn't due to the language itself, but the libraries linked behind it. I emphasize linked, because you don't even write actual symbolic evaluation utilities in Mathematica itself, they wrote that in an entirely different language, and give you a simple interface to those utilities. If that doesn't speak to how bad the language is for it's own use case, I'm not sure what does. Unfortunately many of these implementations are non trivial, and the only thing that arguably rivals it, sympy, gets stuck with trivial symbolic equations. On top of that, because Mathematica is paid, they don't opensource these things, so better languages and ecosystems can't take advantage of the work they did on their inferior language.
So one more thing I'd like to point out, there are attempts to have "one language" languages, many languages have "converged" to have so many utilities that they serve extremely broad niches. One of the most famous and oldest examples, was Algol 60. It was supposed to be the successor to previous versions of Algol, and included a whole bunch of other programming paradigms inside of it. IIRC, it didn't have a successful compiler implemented for it, it was too big.
But other languages have followed in its footsteps. C++ being a very very reminiscent example. C++ has expanded to include functional paradigms, imperative declarative. C++ has expanded to attempt to actually fill all possible niches, from low to high. Now, ignoring arguments of how well it's actually managed to do these kinds of things, C++ has basically run into the algol situation, as of C++20. C++20, in 2022, does not have a complete implementation. 2+years after the finalization of the standard, there's no compiler that supports everything in c++20.
But another thing I'd like to mention, is metaprogramming. A very popular proposal to C++ would have added MetaClasses to the language, a facility that would have brought, implicitly many of the facilities found in C#/Java OOP, properties and many other features. I bring this up to bring up the tendency for large updated programming languages to have features meant to implement other features. Features that overlap heavily into what were the niches of other programming languages. C++ is not alone in this. In swift you can overload any operator, and it similarly has a powerful meta programming capability. In Python, you can modify the AST of the language itself at runtime, allowing you to implement powerful language extensions with out new compiler extensions or other advanced tools. In Rust, despite implementations of it being compiled, you can use macros to emulate almost every feature imaginable, though it will often slow compile time, as macros in rust work off of the abstract syntax tree.
And there's often good reason for people not wanting to jump ship to another DSL for certain workloads. Each of the languages I've discussed, each has their own downsides their own major faults maybe acceptable to a select few people, but not acceptable to everyone. So people wish to stick to their own languages for all these facilities, and develop language features that enable them to do this. Tooling comes packed in with their own language already, and they don't have to worry about odd build system interactions either.
While there is a push in many large popular languages to be able to fill virtually every niche, there's still value to DSLs. A really good example of this, and probably the only really good example of this, is SQL. While SQL has a lot of dialects, SQL is independently compiled from your host program running the queries, and is very small, and allows you to more easily construct database queries and actions vs most native general purpose programming language.
Now there are funnily enough a few issues with this view still, many programming languages embedd SQL syntax into themselves. C and C++ have tools that do this, Rust has libraries that have macros that sort of do this. Still the spirit of a DSL is still there.
The other major issue is that SQL itself is... bad for a query language. In another example of not-the-best-tool being in use because people use it, SQL, and most of its modifications and derivatives, are arguable outclassed by Datalog, an modification to a language called prolog which was never meant to be a data base query language. That's pretty sad. One of the major culprits of the failures of SQL were the original designers at IBM of the language... who instead of using pre-defined relational algebra and relational calculus, formal mathematical models which had been in use for decades prior and unlike other "mathematical models" are much simpler than than what we practically use today, decided to just... not use them...
One more aspect:
Every non-trivial software project uses its own, problem-specific language. So, effectively, we have millions of programming languages in use.
How that?
Bigger software projects always consist of multiple layers, where the lower-level (library) functions help to make the higher-level ones easier to write and understand.
Designing software in layers effectively means to create (in the lower layer) the vocabulary you want to use in the next-higher layer, thus creating the language you want to use for expressing your solution.
So, in a way, there are no two programs using the same language, as they all introduce lots of problem-specific vocabulary.
With bigger software projects, knowing the base programming language (like C, Python or Java) is by far the less challenging task. Understanding the problem-specific vocabulary (framework, classes, fields, methods, ...) plays a much greater role.
So, effectively, the top software layer for a given problem will look very much the same, no matter what base language was chosen. Only, it's packed into the syntax of the base language. E.g. using Java syntax (but would look quite similar in C, C++, C# and a lot of others)
Problem problem = readProblem();
Solution solution = computeSolution(problem);
writeSolution(solution);
Even in an "exotic" language like LISP, you'd recognize the same pattern:
(let* ((problem (read-problem))
(solution (compute-solution problem)))
(write-solution solution))
You see, there's much more problem-specific vocabulary than base language in these lines of code.
So, why do we still have different base languages? Because we choose a language where the base concepts plus the available libraries come close to the problem-domain. If we choose the wrong base language, we waste development effort (= money) for creating the vocabulary for the higher-level functions that come for free in other languages.
From a pragmatic (software engineering) perspective...
The world is filled with pre-existing pieces of software, written in different languages. Even if someone invented a new "perfect" programming language overnight, all this existing code would not just automatically disappear. It would remain in use, and someone would need to maintain it. So the new "perfect" language would just be one more language in that heterogeneous landscape.
Now, if that new language was so good, maybe people would like to translate existing code into the new language. Manual translation would usually be unthinkable (too much code!). Automatic translation might be a possibility, but would often result in the following:
Regarding the last point, consider hardware. Some languages are much "closer to the metal", others are much more abstract. Translation between "high-level" abstract languages running on powerful hardware is feasible (nevermind the potential loss of performance, or the extra resources needed, just increase your CPU and/or add more RAM). The same cannot be said of embedded software running on much more specific and limited hardware.
Consider also the human factor: new language may be great, but existing programmers may find it tedious (and a risky investment of their time) to learn yet another new language. Hence the slow adoption. Also, more money might be made by specialising in maintaining all the old libraries...
There is a conflict of interest between organisations and developers which I believe is partly responsible for the creation and adoption of new languages.
Organisations would probably want a single universal language because it would drive salaries down.
However an individual developer would be well advised to stay ahead of the curve and learn additional languages because it will improve their earning potential.
One language is better.
Unfortunately, no, it is not.
A language is a tool with specific tasks in mind. We don't go around thinking that we only need a hammer, and we don't need to worry about pliers, screwdrivers or saws just because we have a good hammer (and it is a lot easier to learn how to use a hammer than using all those other tools.)