Some constants (true
, false
, null
, maybe some others in specific languages) are so important that they need to be in scope everywhere. It would cause major problems if the user were allowed to shadow them, and it would be very inconvenient if they were only accessible through qualified names like Boolean.TRUE
. By making these keywords, the user cannot declare variables with the same names, and then shadowing is impossible.
In languages where all variables are mutable (i.e. "constants" are just variables you choose not to reassign), it would even be a "WTF" for fundamental constants to be treated the same way as other variables. In very old versions of Python it's legal to redefine True
, False
and None
, and in Javascript (in "sloppy" mode) it's legal to redefine undefined
. Many people found this ridiculous, and it was fixed in later versions of Python and strict-mode Javascript.
On the other hand, keywords are part of the language grammar, and if you did this for every constant then the grammar would change every time you add a new constant to the standard library, and this would invalidate existing code which uses those names for variables. (Keyword constants can't be contextual or "soft" keywords like match
in Python, because they appear in the same contexts as variable names anyway.)
Additionally, constants like PI
or MAX_INT
aren't used practically everywhere, and don't necessarily need to always be in scope or be protected against shadowing. So in these cases I think it makes more sense to treat them like regular constants or variables, with the same semantics as those that users are able to define.
_Bool
type andstdbool.h
have been replaced by abool
type with valuestrue
andfalse
(see cppreference) $\endgroup$None
,True
andFalse
are keywords rather than valid identifiers,__builtins__
is a predefined dictionary in the global scope, andmath.pi
is a constant in a separate module. $\endgroup$