TL;DR: No.
You raise a number of points, and a number of answers were given. I'll play Devil's Advocate and refute most/all of them.
Compiler Complexity and Performance
I suspect that more keywords may make implementing a compiler more complicated, slower as there are more keywords to compare tokens against or similar
On the contrary.
Compiler complexity is typically proportional to the number of concepts that the compiler has to deal with, and how much context the compiler needs to reconstruct (type inference, for example).
Using concepts with no keywords, or overloading keywords to mean multiple concepts in different contexts increases the amount of information the compiler must re-calculate (that the developer knew about) and therefore slows down compilation.
From a compiler perspective, one concept = one unique keyword is actually best.
Backward Compatibility
Or the inability to introduce a new keyword because it would prevent compiling older programs.
This is certainly an issue in many languages. Work-arounds include:
- Using non-keywords: C++ uses
= 0
for pure virtual functions, for example.
- Using contextual keywords: C++ uses
final
and override
as keywords only in function declarations.
- Overloading existing keywords: C++ uses
static
in 4 different ways, with drastically different meanings.
And demonstrates an embarrassing lack of foresight.
A modern1 language should plan for evolution, and thereby figure out a solution to be able to introduce keywords without breaking backwards compatibility.
Examples:
- Prefixing: if keywords start with
:
, and identifiers cannot, then there's no clash possible.
- Versioning: in Rust, each edition introduces new keywords, and users opt-in to the new editions, fixing their code as they do2.
Thus, in a properly crafted language -- easier in hindsight -- there is no backward compatibility issue in adding keywords.
1: By which I mean a language created nowadays, with over 50 years of hindsight.
2: This is supported by another feature, which allow importing identifiers from previous versions, called Raw Identifiers. In essence, it applies the sigil strategy to identifiers (exceptionally), rather than keywords.
Reducing Reserved Words
There are many kinds of keywords.
The "traditional" keyword is reserved at all scopes, and there may be indeed a desire to keep that number low. There are, however, also contextual keywords, which are only keywords in certain contexts.
As an example, consider the (dubious) Rust test case:
fn union() {
union union<'union> { union: &'union union<'union>, }
}
union
is a keyword, when introducing an item, but otherwise can be used as function name, type name, lifetime name, and field name.
Other approaches to avoid "encroaching" on user variables exist, such as the unpopular option of prefix every keyword with a specific sigil3.
3 In this Rust example, single-quote is used as a sigil for lifetimes.
Simplicity and Learning Curve
The difficulty in learning a programming language is generally about semantics -- concepts -- and libraries -- standard or 3rd-party.
Having a single unique keyword for every concept is actually helpful for learners, as they make it easy to:
- Recognize concepts they have not learned yet.
- Search for them -- by keyword! -- on the web.
Keyword-less approaches, or keywords overloading, make a programming language less discoverable as it makes formulating web search queries more difficult, and reduces the pertinence of the search results.
Conclusion
One may want to reduce the number of concepts to keep a language simpler, both for users and compiler-writers.
Reducing the number of keywords without reducing the number of concepts, however, is foolish. If anything, it makes the language harder to learn.
On the other hand, one may want to use mostly contextual keywords, to avoid reserving too many desirable user-defined names.
And of course, one should plan for evolution and have a plan to introduce new keywords in the future. External versioning is a potential solution.