<p>In many languages, the authors are hesitant to add more keywords, because doing so would break any existing code that happens to use those keywords as identifiers. However, they could do what C is doing for <code>bool</code> <code>true</code> and <code>false</code> by building them in but not reserving them as keywords. So if someone has an existing variable named any of those the code will still compile.</p>
<p>Are there any disadvantages to this practice that avoids breaking legacy codebases?</p>

<keywords><backwards-compatibility>
Why do keywords have to be reserved words?
CC BY-SA 4.0
2023-07-07T00:21:18.760Z
Strictly speaking they don't _have_ to. I've seen a code snippet something like `if if = then then then = else else else = if` floating around in the comments here. I'll let someone more familiar with those languages write a full answer.
Bbrk24
CC BY-SA 4.0
2023-07-08T13:12:48.927Z
@Bbrk24 that would be the Fortran classic: https://langdev.stackexchange.com/questions/1978/are-there-good-reasons-to-minimize-the-number-of-keywords-in-a-language#comment3185_1989
detly
CC BY-SA 4.0
2023-07-08T15:22:28.133Z
Actually, C only defines those identifiers in `<stdbool.h>`.  The actual keywords were created using names previously reserved for future use (beginning with `_`).
Toby Speight
CC BY-SA 4.0
2023-07-08T17:22:47.000Z
@TobySpeight ...until C23. Now, `bool` `true` `false` are keywords.
CPlus
CC BY-SA 4.0
2023-07-11T11:22:03.103Z
https://langdev.stackexchange.com/a/2262/1356
coredump
<p>The existing answers are informative, but I feel that they might lack an overview.</p>
<blockquote>
<p>Why do keywords have to be reserved words?</p>
</blockquote>
<h3>The right answer is that &quot;it depends&quot;.</h3>
<p>Summarizing the other answers, it might be because:</p>
<ol>
<li><p>of the way the language was designed...</p>
<p>a. ...making keywords non-reserved a big syntactic problem</p>
<pre class="lang-php prettyprint-override"><code>// New syntax in PHP to create a closure
$x = fn() =&gt; 'hi';

// Theoretically, let's create a function called 'fn'..
function fn(){
    return 'x';
}

// ..which causes a syntax ambiguity:
$y = [ fn() =&gt; 'bye' ];
// Will $y be an array with one value (a closure like $x),
// or will it be ['x' =&gt; 'bye'] ?
</code></pre>
<p>b. ...or not a problem at all (as per the Fortran example mentioned earlier)</p>
</li>
<li><p>it might be also be an intentional design decision, to avoid ambiguities:</p>
<pre class="lang-js prettyprint-override"><code>let definitelyTrue = true;
let true = false;

if (definitelyTrue === true) {
   // this won't work as expected
}

// imagine the havoc of doing the same with a global variable:
window.true = false;
</code></pre>
</li>
<li><p>it may also drastically simplify and speed up parsing or execution. Consider the various function-like constructs in PHP; if PHP allowed redeclaration as functions, it would need to search in the symbol table on each use. Instead, it knows there can't be such a function, so it's extremely fast.</p>
<pre class="lang-php prettyprint-override"><code>exit(1);              // reserved language construct; very fast
array_merge($a, $b);  // standard PHP function; quite slower (even if built-in)
</code></pre>
<p>(this is also why it's recommended to use operators like <code>$x[] = $y</code> instead of functions like <code>array_push()</code>)</p>
</li>
<li><p>in some cases, it could just be a decision of the language vendor, possibly without any specific reasons or even just to follow the crowd.</p>
</li>
<li><p>it could also relate to standards compliance, e.g. if the language want to comply with some specific language standard or dialect</p>
</li>
</ol>

CC BY-SA 4.0
2023-07-08T11:44:36.593Z
2023-07-08T11:44:36.593Z
Christian
<p>When writing a compiler front-end, if you reserve some words as keywords it simplifies writing the BNF (or whatever notation you use) for the language.</p>
<p>The point of syntax notation is to turn a stream of tokens into an abstract syntax tree which actually represents what the coder intended for the program to do.  It's simpler if you know in advance which ones are variables and which ones are language keywords.</p>
<p>Then again, you can do a first-pass over the source code to figure out which identifiers are which, then do a second pass to create the actual AST.</p>
<p>This sounds like a high-cost operation, but some languages don't allow declarations outside of classes, which can be buffered, allowing the dual pass to be made on each class rather than the entire codebase, so doing two passes isn't really so awful.</p>
<p>So it's a tradeoff.  You put less effort into your front-end by reserving keywords, but you can get away with not doing so with a little additional work.</p>
<p>If you take the additional effort, you can add keywords without breaking older code.  Whether that's worth the trouble is a judgment call.</p>

CC BY-SA 4.0
2023-07-08T02:17:09.920Z
2023-07-08T02:17:09.920Z
RLWatkins
CC BY-SA 4.0
2023-07-09T16:18:37.830Z
Note that only certain keywords would be treated as reserved to achieve this goal.  Many languages include keywords which could be treated grammatically as ordinary identifiers.  In Pascal, if one were to try to write `Nil := myPointer;`, while such an assignment could be forbidden at the parsing level (since Nil isn't an identifier), treating NIl as an identifier up until the point one tries to actually interpret it as a variable reference would also work just fine.
supercat
<p>There's also the option, of course, of treating newly-added keywords as not reserved words while any pre-existing keywords remain reserved, like <a href="https://peps.python.org/pep-0492/#transition-plan" rel="nofollow noreferrer">Python did for a few versions with Async and Await</a>. While they removed that feature in later versions after a deprecation period, it could just as easily have remained forever.</p>

CC BY-SA 4.0
2023-07-07T02:49:53.707Z
2023-07-07T02:49:53.707Z
pppery
CC BY-SA 4.0
2023-07-11T15:51:17.323Z
It's still the case with `match` in Python, and AFAIK they don't plan on reserving it ever, since `match` is also used as a name for functions/methods/variables in a lot of libraries/code
CoffeeTableEspresso
<h2>Ambiguity</h2>
<p>Especially in beginner languages, ambiguity can be problematic. Statements like:</p>
<pre><code>false = true
if false == false
</code></pre>
<p>can be confusing for new users of a language, as it can be hard to tell whether the false on the left is a boolean or a variable name. Misinterpretations of the statement can lead to inaccuracy (if the false on the left is interpreted as a variable name, the if statement will produce false, but if it is interpreted as the boolean, it will produce true.)</p>
<p>Another case of ambiguity:</p>
<pre><code>import pandas as pd
pd = pd.DataFrame(stuff)
x = pd.read_csv(more stuff)
</code></pre>
<p>In this case, it may be hard for a beginner to determine whether read_csv() is a function of the pd DataFrame or the pd pandas library. (I tested this, by the way, and it crashed the program.)</p>

CC BY-SA 4.0
2023-07-07T00:27:58.520Z
2023-07-07T00:27:58.520Z
Redz
CC BY-SA 4.0
2023-07-07T10:28:10.410Z
`False = True` used to be possible before Python 3
Kien Truong
CC BY-SA 4.0
2023-07-08T05:29:18.087Z
While I see how the stuff with Pandas is related, I don't see how it's the same thing. And what do you mean it "crashed" the program? Did it hang the kernel? Did it raise an error? I tried it (replacing "more stuff" with "more_stuff"), and it said that DataFrames don't have read_csv, which is what I expected. There's no ambiguity: once you bind pd.DataFrame(stuff) to pd, pd is a DataFrame. It's no different in principle from `a = [1,2] a = a[1] print(a[1])`. You can bind a variable name to something contained in what it was previously bound to. There's no ambiguity as to what that does.
Acccumulation
<p>Ambiguity is the primary reason, as others have explained. I would like to also add that in a language without reserved keywords, it's very easy to shadow basic constructs, like <code>if</code>. This code works in Bash (but not when in POSIX mode):</p>
<pre><code>$ alias if=echo
$ if true
true
$ if true; then echo yes; fi
bash: syntax error near unexpected token `then'
$ unalias if
$ if true; then echo yes; fi
yes
</code></pre>
<hr />
<p>Instead of the fully reserved keywords, one way to introduce keywords without breaking old code is Contextual Keywords.</p>
<p>Basically you introduce keywords that can only be used in places where normal identifiers cannot. For example, <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/#contextual-keywords" rel="nofollow noreferrer">C#</a> did that with newer keywords, so did <a href="https://stackoverflow.com/a/59823299">Kotlin</a>, but <a href="https://stackoverflow.com/questions/8099270/use-of-reserved-words-in-javascript">JavaScript</a> did the opposite and allowed <em>all</em> keywords in certain places like dot-notation and object literals (eg, both <code>x = { if: 1 }</code> and <code>x.if</code> became legal).</p>
<p>You can also provide a &quot;quoting mechanism&quot; to allow reserved words (or, depending on your use case, even illegal characters, including punctuation, spaces, and even newlines) to be used as identifiers: <a href="https://stackoverflow.com/questions/6639688/using-keywords-as-identifiers-in-f#6639705">C#, VB.NET, F#</a>, and <a href="https://doc.rust-lang.org/rust-by-example/compatibility/raw_identifiers.html" rel="nofollow noreferrer">Rust</a>, and <a href="https://kotlinlang.org/spec/syntax-and-grammar.html#grammar-rule-Letter" rel="nofollow noreferrer">Kotlin</a>, and SQL has &quot;delimited identifiers&quot;, and others. This general trick is called <a href="https://en.wikipedia.org/wiki/Stropping_(syntax)#Modern_use" rel="nofollow noreferrer">Stropping</a>.</p>

CC BY-SA 4.0
2023-07-07T18:41:09.647Z
2023-07-08T15:58:33.940Z
2023-07-08T15:58:33.940Z
Noureddin
CC BY-SA 4.0
2023-07-07T18:53:13.607Z
Kotlin has quoting too
Seggan
CC BY-SA 4.0
2023-07-08T16:00:36.587Z
@Seggan, Thank you. I've just added Kotlin. I've also found that it supported "Soft Keywords" (what C# called Contextual Keywords).
Noureddin
<h2>Better compiler error handling</h2>
<p>When producing parsing errors, a compiler (or interpreter, if you're into that) which disallows keywords being used in other contexts can much more easily isolate the issue, and continue looking for other errors to report. E.g., this C/Rust/JS-hybrid pseudocode would make it very difficult for the compiler to be sure how to parse everything after the first line:</p>
<pre><code>type function == Callable; // Oops! Supposed to be one '='

function function() { // function keyword is 'function'
    function function = function() || function() { function }; // recurse, or default to an anonymous function, and assign with C-style syntax to a local variable shadowing the top-level 'function' function

    function // implicit return
}
</code></pre>
<p>While something as ridiculous as this would never occur in practical code, it'd be much easier to recover from that small parsing issue at the start if, e.g., <code>function</code> was <em>always</em> a keyword. It's also harder to provide useful error messages when there are many different things that could have been meant by one string (e.g., both a keyword and a type, or both a keyword and an identifier, or all three as in the code above).</p>

CC BY-SA 4.0
2023-07-07T02:09:30.320Z
2023-07-07T02:09:30.320Z
rydwolf
CC BY-SA 4.0
2023-07-07T17:44:48.213Z
A related issue: keywords that aren't always used as keywords can make syntax highlighting more difficult (not impossible, but more complicated to implement).
DLosc
<blockquote>
<p>Why do keywords have to be reserved words?</p>
</blockquote>
<p>They don't.
The designers of a language must decide, very early in the process, whether keywords will also be reserved words.</p>
<p>Fortran for instance has gotten along quite well for two thirds of a century without requiring that its keywords also be reserved words:</p>
<blockquote>
<p>Keywords are specifically NOT reserved words as per the Fortran specifications (F03 section 2.52, F90 section 2.52, and F77 section 2.2).<br />
— <a href="https://fortranwiki.org/fortran/show/Keywords" rel="noreferrer">Keywords in Fortran</a></p>
</blockquote>
<p>It's only when a language's designers decide to reserve specific keywords (or don't even think about it), that potential problems arise.</p>
<p>(One simple way of getting the best of both worlds is to provide a simple rule that defines <em>all</em> reserved words, past, present, and future.
E.g. all identifiers that begin with &quot;_&quot; are reserved, and no other identifiers will ever be reserved.)</p>

CC BY-SA 4.0
2023-07-07T00:53:19.727Z
2023-07-07T00:53:19.727Z
Ray Butterworth
CC BY-SA 4.0
2023-07-07T08:17:30.873Z
About your final note: APLs tend to do this. APL uses prefix `⎕` and `:` for all reserved words, J uses suffix `.` and BQN uses prefix `•`.
Adám
CC BY-SA 4.0
2023-07-07T14:02:47.950Z
SQL also has a mixed of reserved and non-reserved keywords.
Barmar
CC BY-SA 4.0
2023-07-09T16:23:36.743Z
It's also possible for keywords to be marked with special symbols.  This is commonly done with things like assembler directives or C preprocessor directives, but could also be done with things like operators.  If a C-like language had a rule that structure-access operator must not be preceded by whitespace, and operators like `.ediv.` or `.rdiv.` [Euclidian or rounding integer division] had to be preceded and followed by white space, the language could add new operator keywords without creating ambiguity.
supercat
CC BY-SA 4.0
2023-07-10T08:13:56.340Z
@supercat "In the Revised Report, **Algol 68** is written in lower-case letters, with keywords emphasized in bold. Text files [...] don’t provide a mechanism for the representation of bold text, so keywords are typically written in upper-case [...]. The original Algol 68-R compiler [...] had a basic character set of only 64 characters. Lower-case characters were available only through a complicated system of shift prefixes, and weren’t used in programming. In Algol 68-R, keywords were distinguished from identifiers by enclosing them in single quotes, which was called ‘quote stropping’."
Peter - Reinstate Monica
CC BY-SA 4.0
2023-07-10T08:14:15.900Z
@supercat From https://accu.org/journals/overload/26/148/james_2586/
Peter - Reinstate Monica
# Why do keywords have to be reserved words?
Posted by: username_0 on 2023-07-07
In many languages, the authors are hesitant to add more keywords, because doing so would break any existing code that happens to use those keywords as identifiers. However, they could do what C is doing for `bool` `true` and `false` by building them in but not reserving them as keywords. So if someone has an existing variable named any of those the code will still compile.

Are there any disadvantages to this practice that avoids breaking legacy codebases?
**Tags:** keywords backwards-compatibility
> **Comments:**
> **username_1**: Strictly speaking they don't _have_ to. I've seen a code snippet something like `if if = then then then = else else else = if` floating around in the comments here. I'll let someone more familiar with those languages write a full answer.  
> **username_2**: @Bbrk24 that would be the Fortran classic: https://langdev.stackexchange.com/questions/1978/are-there-good-reasons-to-minimize-the-number-of-keywords-in-a-language#comment3185_1989  
> **username_3**: Actually, C only defines those identifiers in `<stdbool.h>`.  The actual keywords were created using names previously reserved for future use (beginning with `_`).  
> **username_0**: @TobySpeight ...until C23. Now, `bool` `true` `false` are keywords.  
> **username_4**: https://langdev.stackexchange.com/a/2262/1356  
---
## 7 answers
### Answer by username_17 on 2023-07-07. Score: 16
> Why do keywords have to be reserved words?

They don't.
The designers of a language must decide, very early in the process, whether keywords will also be reserved words.

Fortran for instance has gotten along quite well for two thirds of a century without requiring that its keywords also be reserved words:

> Keywords are specifically NOT reserved words as per the Fortran specifications (F03 section 2.52, F90 section 2.52, and F77 section 2.2).  
> — [Keywords in Fortran](https://fortranwiki.org/fortran/show/Keywords)

It's only when a language's designers decide to reserve specific keywords (or don't even think about it), that potential problems arise.

(One simple way of getting the best of both worlds is to provide a simple rule that defines *all* reserved words, past, present, and future.
E.g. all identifiers that begin with "\_" are reserved, and no other identifiers will ever be reserved.)
> **Comments:**
> **username_18** (2023-07-07): About your final note: APLs tend to do this. APL uses prefix `⎕` and `:` for all reserved words, J uses suffix `.` and BQN uses prefix `•`.  
> **username_19** (2023-07-07): SQL also has a mixed of reserved and non-reserved keywords.  
> **username_7** (2023-07-09): It's also possible for keywords to be marked with special symbols.  This is commonly done with things like assembler directives or C preprocessor directives, but could also be done with things like operators.  If a C-like language had a rule that structure-access operator must not be preceded by whitespace, and operators like `.ediv.` or `.rdiv.` [Euclidian or rounding integer division] had to be preceded and followed by white space, the language could add new operator keywords without creating ambiguity.  
> **username_20** (2023-07-10): @supercat "In the Revised Report, **Algol 68** is written in lower-case letters, with keywords emphasized in bold. Text files [...] don’t provide a mechanism for the representation of bold text, so keywords are typically written in upper-case [...]. The original Algol 68-R compiler [...] had a basic character set of only 64 characters. Lower-case characters were available only through a complicated system of shift prefixes, and weren’t used in programming. In Algol 68-R, keywords were distinguished from identifiers by enclosing them in single quotes, which was called ‘quote stropping’."  
> **username_20** (2023-07-10): @supercat From https://accu.org/journals/overload/26/148/james_2586/  
---
### Answer by username_15 on 2023-07-07. Score: 14
Better compiler error handling
When producing parsing errors, a compiler (or interpreter, if you're into that) which disallows keywords being used in other contexts can much more easily isolate the issue, and continue looking for other errors to report. E.g., this C/Rust/JS-hybrid pseudocode would make it very difficult for the compiler to be sure how to parse everything after the first line:
type function == Callable; // Oops! Supposed to be one '='

function function() { // function keyword is 'function'
    function function = function() || function() { function }; // recurse, or default to an anonymous function, and assign with C-style syntax to a local variable shadowing the top-level 'function' function

    function // implicit return
}

While something as ridiculous as this would never occur in practical code, it'd be much easier to recover from that small parsing issue at the start if, e.g., function was always a keyword. It's also harder to provide useful error messages when there are many different things that could have been meant by one string (e.g., both a keyword and a type, or both a keyword and an identifier, or all three as in the code above).
> **Comments:**
> **username_16** (2023-07-07): A related issue: keywords that aren't always used as keywords can make syntax highlighting more difficult (not impossible, but more complicated to implement).  
---
### Answer by username_10 on 2023-07-07. Score: 7
Ambiguity
Especially in beginner languages, ambiguity can be problematic. Statements like:
false = true
if false == false

can be confusing for new users of a language, as it can be hard to tell whether the false on the left is a boolean or a variable name. Misinterpretations of the statement can lead to inaccuracy (if the false on the left is interpreted as a variable name, the if statement will produce false, but if it is interpreted as the boolean, it will produce true.)
Another case of ambiguity:
import pandas as pd
pd = pd.DataFrame(stuff)
x = pd.read_csv(more stuff)

In this case, it may be hard for a beginner to determine whether read_csv() is a function of the pd DataFrame or the pd pandas library. (I tested this, by the way, and it crashed the program.)
> **Comments:**
> **username_11** (2023-07-07): `False = True` used to be possible before Python 3  
> **username_12** (2023-07-08): While I see how the stuff with Pandas is related, I don't see how it's the same thing. And what do you mean it "crashed" the program? Did it hang the kernel? Did it raise an error? I tried it (replacing "more stuff" with "more_stuff"), and it said that DataFrames don't have read_csv, which is what I expected. There's no ambiguity: once you bind pd.DataFrame(stuff) to pd, pd is a DataFrame. It's no different in principle from `a = [1,2] a = a[1] print(a[1])`. You can bind a variable name to something contained in what it was previously bound to. There's no ambiguity as to what that does.  
---
### Answer by username_13 on 2023-07-07. Score: 7
Ambiguity is the primary reason, as others have explained. I would like to also add that in a language without reserved keywords, it's very easy to shadow basic constructs, like if. This code works in Bash (but not when in POSIX mode):
$ alias if=echo
$ if true
true
$ if true; then echo yes; fi
bash: syntax error near unexpected token `then'
$ unalias if
$ if true; then echo yes; fi
yes


Instead of the fully reserved keywords, one way to introduce keywords without breaking old code is Contextual Keywords.
Basically you introduce keywords that can only be used in places where normal identifiers cannot. For example, C# did that with newer keywords, so did Kotlin, but JavaScript did the opposite and allowed all keywords in certain places like dot-notation and object literals (eg, both x = { if: 1 } and x.if became legal).
You can also provide a "quoting mechanism" to allow reserved words (or, depending on your use case, even illegal characters, including punctuation, spaces, and even newlines) to be used as identifiers: C#, VB.NET, F#, and Rust, and Kotlin, and SQL has "delimited identifiers", and others. This general trick is called Stropping.
> **Comments:**
> **username_14** (2023-07-07): Kotlin has quoting too  
> **username_13** (2023-07-08): @Seggan, Thank you. I've just added Kotlin. I've also found that it supported "Soft Keywords" (what C# called Contextual Keywords).  
---
### Answer by username_5 on 2023-07-08. Score: 5
The existing answers are informative, but I feel that they might lack an overview.

Why do keywords have to be reserved words?

The right answer is that "it depends".
Summarizing the other answers, it might be because:

of the way the language was designed...
a. ...making keywords non-reserved a big syntactic problem
// New syntax in PHP to create a closure
$x = fn() => 'hi';

// Theoretically, let's create a function called 'fn'..
function fn(){
    return 'x';
}

// ..which causes a syntax ambiguity:
$y = [ fn() => 'bye' ];
// Will $y be an array with one value (a closure like $x),
// or will it be ['x' => 'bye'] ?

b. ...or not a problem at all (as per the Fortran example mentioned earlier)

it might be also be an intentional design decision, to avoid ambiguities:
let definitelyTrue = true;
let true = false;

if (definitelyTrue === true) {
   // this won't work as expected
}

// imagine the havoc of doing the same with a global variable:
window.true = false;


it may also drastically simplify and speed up parsing or execution. Consider the various function-like constructs in PHP; if PHP allowed redeclaration as functions, it would need to search in the symbol table on each use. Instead, it knows there can't be such a function, so it's extremely fast.
exit(1);              // reserved language construct; very fast
array_merge($a, $b);  // standard PHP function; quite slower (even if built-in)

(this is also why it's recommended to use operators like $x[] = $y instead of functions like array_push())

in some cases, it could just be a decision of the language vendor, possibly without any specific reasons or even just to follow the crowd.

it could also relate to standards compliance, e.g. if the language want to comply with some specific language standard or dialect
---
### Answer by username_6 on 2023-07-08. Score: 4
When writing a compiler front-end, if you reserve some words as keywords it simplifies writing the BNF (or whatever notation you use) for the language.

The point of syntax notation is to turn a stream of tokens into an abstract syntax tree which actually represents what the coder intended for the program to do. It's simpler if you know in advance which ones are variables and which ones are language keywords.

Then again, you can do a first-pass over the source code to figure out which identifiers are which, then do a second pass to create the actual AST.

This sounds like a high-cost operation, but some languages don't allow declarations outside of classes, which can be buffered, allowing the dual pass to be made on each class rather than the entire codebase, so doing two passes isn't really so awful.

So it's a tradeoff. You put less effort into your front-end by reserving keywords, but you can get away with not doing so with a little additional work.

If you take the additional effort, you can add keywords without breaking older code. Whether that's worth the trouble is a judgment call.
> **Comments:**
> **username_7** (2023-07-09): Note that only certain keywords would be treated as reserved to achieve this goal.  Many languages include keywords which could be treated grammatically as ordinary identifiers.  In Pascal, if one were to try to write `Nil := myPointer;`, while such an assignment could be forbidden at the parsing level (since Nil isn't an identifier), treating NIl as an identifier up until the point one tries to actually interpret it as a variable reference would also work just fine.  
---
### Answer by username_8 on 2023-07-07. Score: 4
There's also the option, of course, of treating newly-added keywords as not reserved words while any pre-existing keywords remain reserved, like [Python did for a few versions with Async and Await](https://peps.python.org/pep-0492/#transition-plan). While they removed that feature in later versions after a deprecation period, it could just as easily have remained forever.
> **Comments:**
> **username_9** (2023-07-11): It's still the case with `match` in Python, and AFAIK they don't plan on reserving it ever, since `match` is also used as a name for functions/methods/variables in a lot of libraries/code  
---
