<p>As of C17 there are no built-in constants. To use <code>true</code> <code>false</code> <code>NULL</code> or similar one must <code>#include</code> various header files. However this will change in C23 and <code>true</code> <code>false</code> and <code>bool</code> will be keywords.</p>
<p>In Java there is <code>Math.PI</code> instead of having <code>PI</code> or <code>pi</code> as a keyword.</p>
<p>Is there any reason to do that as opposed to just making them keywords that behave as literals? What are the advantages and disadvantages of having constants built-in versus having them imported from library/header files?</p>

<standard-library><keywords><built-ins>
Are there any reasons not to have built-in constants?
CC BY-SA 4.0
2023-07-04T16:49:42.603Z
Note that in C23 the `_Bool` type and `stdbool.h` have been replaced by a `bool` type with values `true` and `false` (see [cppreference](https://en.cppreference.com/w/c/language/bool_constant))
RubenVerg
CC BY-SA 4.0
2023-07-04T16:50:59.327Z
@RubenVerg That is correct.
CPlus
CC BY-SA 4.0
2023-07-04T16:51:05.917Z
This is two separate things - firstly whether they should be keywords, and secondly whether they should be available in the global scope. (If they're keywords then the answer to the second part seems to be obviously yes.) Python exhibits all three options ─ `None`, `True` and `False` are keywords rather than valid identifiers, `__builtins__` is a predefined dictionary in the global scope, and `math.pi` is a constant in a separate module.
kaya3
CC BY-SA 4.0
2023-07-04T16:57:01.437Z
@user16217248-OnStrike missed the 17 in C17, sorry, guess this is interesting anyways
RubenVerg
<p>Some constants (<code>true</code>, <code>false</code>, <code>null</code>, 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 <code>Boolean.TRUE</code>. By making these keywords, the user cannot declare variables with the same names, and then shadowing is impossible.</p>
<p>In languages where all variables are mutable (i.e. &quot;constants&quot; are just variables you choose not to reassign), it would even be a &quot;WTF&quot; for fundamental constants to be treated the same way as other variables. In very <a href="https://stackoverflow.com/a/2535491/12299000">old versions of Python</a> it's legal to redefine <code>True</code>, <code>False</code> and <code>None</code>, and <a href="https://stackoverflow.com/a/790615/12299000">in Javascript</a> (in &quot;sloppy&quot; mode) it's legal to redefine <code>undefined</code>. Many people found this ridiculous, and it was fixed in later versions of Python and strict-mode Javascript.</p>
<p>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 <a href="https://docs.python.org/3/reference/lexical_analysis.html#soft-keywords" rel="noreferrer">&quot;soft&quot; keywords</a> like <code>match</code> in Python, because they appear in the same contexts as variable names anyway.)</p>
<p>Additionally, constants like <code>PI</code> or <code>MAX_INT</code> 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.</p>

CC BY-SA 4.0
2023-07-04T17:38:56.953Z
2023-07-04T17:38:56.953Z
kaya3
CC BY-SA 4.0
2023-07-04T17:45:16.057Z
Obligatory mention of `false become:true` in some dialects of Smalltalk.
Bbrk24
CC BY-SA 4.0
2023-07-04T18:42:09.200Z
You still can redefine Python3's constants: CPython boxes them all and caches a few of them on startup, and `id` returns the shared objects' locations. `ctypes.c_int8.from_address(id(4) + 24).value = 5` rewrites `4` to `5`.
Longinus
CC BY-SA 4.0
2023-07-04T19:03:35.287Z
@Longinus That's true in CPython, but it is not part of the language design. It's also hilarious, because it doesn't just rebind the "name" `4`, it also changes the result of `2 + 2` (due to small integers being cached).
kaya3
CC BY-SA 4.0
2023-07-06T22:21:12.560Z
@Bbrk24 When I was managing Lisp Machines, one of my users once redefined NIL or T. A system crash soon occurred. Symbolics made them constants in the next update.
Barmar
CC BY-SA 4.0
2023-07-07T16:58:52.933Z
It's worth noting `undefined` was never intended to be mutable, but Internet Explorer did what it does best and messed up the implementation, and everyone else kept the behavior for backwards compatibility.
rydwolf
<h2>Because they can be</h2>
<p>There is no real need to give these constants special treatment in the compiler. Normal values would function exactly the same in most cases. Not giving them special treatment but simply defining them in the standard library is easier.</p>
<h2>Not all of them are used very much</h2>
<p>While <code>true</code>, <code>false</code>, and <code>null</code> are common enough to have in global scope, something like PI is only really used in trigonometry. It's not that much effort to type <code>Math.</code> in front of it when you need it.</p>
<p>PI is used in many math formulas with a different meaning than 3.14... If Pi was always in the global scope you couldn't name any variables PI without leaving you unable to access the circle constant.</p>

CC BY-SA 4.0
2023-07-04T16:58:31.763Z
2023-07-04T16:58:31.763Z
mousetail 'he-him'
CC BY-SA 4.0
2023-07-06T22:22:55.517Z
Not to mention politics - Indiana once passed a bill that set π to 3.2.
Barmar
CC BY-SA 4.0
2023-07-07T00:33:11.680Z
@Barmar they didnt actually pass the bill
Seggan
CC BY-SA 4.0
2023-07-07T00:36:06.257Z
@Seggan-OnStrike Their House of Representative passed it, but it died in the Senate.
Barmar
CC BY-SA 4.0
2023-07-07T00:36:38.577Z
@Barmar my point still stands
Seggan
CC BY-SA 4.0
2023-07-07T00:37:38.303Z
@Seggan-OnStrike OK, they *tried* to pass a bill that....
Barmar
<h2>C Has An Infinite Number of Builtin Constants</h2>
<p>C17§6.4.4. and §6.4.5. define four different kinds of builtin constants: integers, floating-point numbers, character constants and string literals.<br />
Each allow for an arbitrary number of either digits or characters (including in character constants).</p>
<p>C does not need to offer any of them as part of its feature set. Integrals can be represented fully using Peano's Numbers:</p>
<pre class="lang-hs prettyprint-override"><code>type 0
type ℤ⁺ : (ℤ⁺ | 0) -&gt; ℤ⁺
type ℤ⁻ : (ℤ⁻ | 0) -&gt; ℤ⁻
ℤ = 0 | ℤ⁺ | ℤ⁻

5 = ℤ⁺ (ℤ⁺ (ℤ⁺ (ℤ⁺ (ℤ⁺ 0))))
-4 = ℤ⁻ (ℤ⁻ (ℤ⁻ (ℤ⁻ 0)))
</code></pre>
<p>Look ma! No builtin numbers!</p>
<p><code>42</code> is as much a keyword as are <code>true</code>, <code>false</code> and <code>null</code>.<br />
Many languages, including C-like ones, don't even have builtin negative literal constants, and instead have a unary minus operator that you apply to numbers.</p>

CC BY-SA 4.0
2023-07-04T19:04:13.780Z
2023-07-04T21:08:20.777Z
2023-07-04T21:08:20.777Z
Longinus
CC BY-SA 4.0
2023-07-04T19:30:34.780Z
-42 isn’t a literal, it’s unary minus applied to 42. This means that INT_MIN can’t be `-2147483648`, it has to be `-2147483647 - 1`.
Bbrk24
CC BY-SA 4.0
2023-07-04T21:05:48.270Z
@Bbrk24 Good point! Many languages only have builtin positive constant literals!
Longinus
<h3>You might not know the type and precision required</h3>
<p>Consider Pi as a constant in a C like language</p>
<p>Should it be a float or a double or a 128 bit precisions float or perhaps even an arbitrary precision <em>bigint</em>?</p>
<p>How many digits do you need?</p>
<p>Though in fact <a href="https://stackoverflow.com/questions/1727881/how-to-use-the-pi-constant-in-c/57285400#57285400">pi has arrived in C++20</a>. That it took so long to get there should hint there are some issues.</p>
<h3>You may be trying to guess your users requirements</h3>
<p>If you provide pi as float but actually most of your users wants a double you have polluted your standard namespace and everyone is rolling their own <em>double_pi</em>.</p>
<h3>what do you mean by builtin?</h3>
<p>Builtin constants are unnecessary bloat if you don't use them.
Maybe I don't have any use for pi in my application.</p>
<h3>Your constant is not as constant as you think</h3>
<p>Say you define PATH_MAX as a builtin constant for the maximum length of a path.
Does that vary by operating system or file system?
Is it something your application should actually get from calling a function at runtime?
See for example <a href="https://eklitzke.org/path-max-is-tricky" rel="nofollow noreferrer">https://eklitzke.org/path-max-is-tricky</a></p>
<h3>Some constants are safe and good</h3>
<p>It seems pretty sane for <em>true</em> and <em>false</em> to be builtin.</p>
<h3>Beware automatic type conversion</h3>
<p>But to give them values of 1 and 0 might be a unwise if your language supports arbitrary conversions to and from different kinds of number.</p>
<p>Booleans may be better off being left as a distinct type.</p>

CC BY-SA 4.0
2023-07-05T00:44:28.323Z
2023-07-05T00:44:28.323Z
Bruce Adams
<h2>Alternative solution: static properties + inferred base type</h2>
<p>Swift has things like this:</p>
<pre class="lang-swift prettyprint-override"><code>extension Double {
  static var pi: Double { 3.14... }
}
</code></pre>
<p>Swift also has inferred base types for static variables:</p>
<pre class="lang-swift prettyprint-override"><code>let x: Double = .pi // inferred as Double.pi
</code></pre>
<p>These extensions can live in other modules, so they don't have to be built-in, but the inferred base types lower the barrier to use, in a sense.</p>

CC BY-SA 4.0
2023-07-04T17:18:37.433Z
2023-07-04T17:18:37.433Z
Bbrk24
# Are there any reasons not to have built-in constants?
Posted by: username_0 on 2023-07-04
As of C17 there are no built-in constants. To use `true` `false` `NULL` or similar one must `#include` various header files. However this will change in C23 and `true` `false` and `bool` will be keywords.

In Java there is `Math.PI` instead of having `PI` or `pi` as a keyword.

Is there any reason to do that as opposed to just making them keywords that behave as literals? What are the advantages and disadvantages of having constants built-in versus having them imported from library/header files?
**Tags:** standard-library keywords built-ins
> **Comments:**
> **username_1**: Note that in C23 the `_Bool` type and `stdbool.h` have been replaced by a `bool` type with values `true` and `false` (see [cppreference](https://en.cppreference.com/w/c/language/bool_constant))  
> **username_0**: @RubenVerg That is correct.  
> **username_2**: This is two separate things - firstly whether they should be keywords, and secondly whether they should be available in the global scope. (If they're keywords then the answer to the second part seems to be obviously yes.) Python exhibits all three options ─ `None`, `True` and `False` are keywords rather than valid identifiers, `__builtins__` is a predefined dictionary in the global scope, and `math.pi` is a constant in a separate module.  
> **username_1**: @user16217248-OnStrike missed the 17 in C17, sorry, guess this is interesting anyways  
---
## 5 answers
### Answer by username_2 on 2023-07-04. Score: 11
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](https://stackoverflow.com/a/2535491/12299000) it's legal to redefine `True`, `False` and `None`, and [in Javascript](https://stackoverflow.com/a/790615/12299000) (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](https://docs.python.org/3/reference/lexical_analysis.html#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.
> **Comments:**
> **username_3** (2023-07-04): Obligatory mention of `false become:true` in some dialects of Smalltalk.  
> **username_4** (2023-07-04): You still can redefine Python3's constants: CPython boxes them all and caches a few of them on startup, and `id` returns the shared objects' locations. `ctypes.c_int8.from_address(id(4) + 24).value = 5` rewrites `4` to `5`.  
> **username_2** (2023-07-04): @Longinus That's true in CPython, but it is not part of the language design. It's also hilarious, because it doesn't just rebind the "name" `4`, it also changes the result of `2 + 2` (due to small integers being cached).  
> **username_5** (2023-07-06): @Bbrk24 When I was managing Lisp Machines, one of my users once redefined NIL or T. A system crash soon occurred. Symbolics made them constants in the next update.  
> **username_6** (2023-07-07): It's worth noting `undefined` was never intended to be mutable, but Internet Explorer did what it does best and messed up the implementation, and everyone else kept the behavior for backwards compatibility.  
---
### Answer by username_7 on 2023-07-04. Score: 5
## Because they can be

There is no real need to give these constants special treatment in the compiler. Normal values would function exactly the same in most cases. Not giving them special treatment but simply defining them in the standard library is easier.

## Not all of them are used very much

While `true`, `false`, and `null` are common enough to have in global scope, something like PI is only really used in trigonometry. It's not that much effort to type `Math.` in front of it when you need it.

PI is used in many math formulas with a different meaning than 3.14... If Pi was always in the global scope you couldn't name any variables PI without leaving you unable to access the circle constant.
> **Comments:**
> **username_5** (2023-07-06): Not to mention politics - Indiana once passed a bill that set π to 3.2.  
> **username_8** (2023-07-07): @Barmar they didnt actually pass the bill  
> **username_5** (2023-07-07): @Seggan-OnStrike Their House of Representative passed it, but it died in the Senate.  
> **username_8** (2023-07-07): @Barmar my point still stands  
> **username_5** (2023-07-07): @Seggan-OnStrike OK, they *tried* to pass a bill that....  
---
### Answer by username_9 on 2023-07-05. Score: 3
### You might not know the type and precision required

Consider Pi as a constant in a C like language

Should it be a float or a double or a 128 bit precisions float or perhaps even an arbitrary precision *bigint*?

How many digits do you need?

Though in fact [pi has arrived in C++20](https://stackoverflow.com/questions/1727881/how-to-use-the-pi-constant-in-c/57285400#57285400). That it took so long to get there should hint there are some issues.

### You may be trying to guess your users requirements

If you provide pi as float but actually most of your users wants a double you have polluted your standard namespace and everyone is rolling their own *double\_pi*.

### what do you mean by builtin?

Builtin constants are unnecessary bloat if you don't use them.
Maybe I don't have any use for pi in my application.

### Your constant is not as constant as you think

Say you define PATH\_MAX as a builtin constant for the maximum length of a path.
Does that vary by operating system or file system?
Is it something your application should actually get from calling a function at runtime?
See for example <https://eklitzke.org/path-max-is-tricky>

### Some constants are safe and good

It seems pretty sane for *true* and *false* to be builtin.

### Beware automatic type conversion

But to give them values of 1 and 0 might be a unwise if your language supports arbitrary conversions to and from different kinds of number.

Booleans may be better off being left as a distinct type.
---
### Answer by username_3 on 2023-07-04. Score: 3
Alternative solution: static properties + inferred base type
Swift has things like this:
extension Double {
  static var pi: Double { 3.14... }
}

Swift also has inferred base types for static variables:
let x: Double = .pi // inferred as Double.pi

These extensions can live in other modules, so they don't have to be built-in, but the inferred base types lower the barrier to use, in a sense.
---
### Answer by username_4 on 2023-07-04. Score: 2
C Has An Infinite Number of Builtin Constants
C17§6.4.4. and §6.4.5. define four different kinds of builtin constants: integers, floating-point numbers, character constants and string literals.
Each allow for an arbitrary number of either digits or characters (including in character constants).
C does not need to offer any of them as part of its feature set. Integrals can be represented fully using Peano's Numbers:
type 0
type ℤ⁺ : (ℤ⁺ | 0) -> ℤ⁺
type ℤ⁻ : (ℤ⁻ | 0) -> ℤ⁻
ℤ = 0 | ℤ⁺ | ℤ⁻

5 = ℤ⁺ (ℤ⁺ (ℤ⁺ (ℤ⁺ (ℤ⁺ 0))))
-4 = ℤ⁻ (ℤ⁻ (ℤ⁻ (ℤ⁻ 0)))

Look ma! No builtin numbers!
42 is as much a keyword as are true, false and null.
Many languages, including C-like ones, don't even have builtin negative literal constants, and instead have a unary minus operator that you apply to numbers.
> **Comments:**
> **username_3** (2023-07-04): -42 isn’t a literal, it’s unary minus applied to 42. This means that INT_MIN can’t be `-2147483648`, it has to be `-2147483647 - 1`.  
> **username_4** (2023-07-04): @Bbrk24 Good point! Many languages only have builtin positive constant literals!  
---
