<p>Some programming languages (Rust is one I can think of off the top of my head) provides mechanisms to have immutable variables but they also have constants. Isn't an immutable variable just a constant? What advantage is there in supporting both?</p>

<variables><immutable>
Why do some languages have both immutable "variables" and constants?
CC BY-SA 4.0
2023-11-19T06:46:40.097Z
Maybe provide some reasoning on why an immutable variable is a constant? You might be able to find some differences.
Redz
CC BY-SA 4.0
2023-11-19T07:26:14.467Z
Is this question about Rust, or about immutabile and constant variables in general? Rust uses *very specific* meanings of both of these terms that are not universal, and an answer that addresses either Rust or the broader case isn’t going to do a good job of the other (in fact, likely be contradictory!). How general is this question intending to be?
Michael Homer
CC BY-SA 4.0
2023-11-19T08:49:19.593Z
If it's not about Rust: an immutable variable still has a location and lifetime, a constant just is.
feldentm
CC BY-SA 4.0
2023-11-19T14:40:34.440Z
I decided to remove the "rust" tag since this question isn't specifically about Rust and I was just using that as one example.
QAH
CC BY-SA 4.0
2023-11-20T11:59:49.670Z
@QAH But in a different language those terms may have different meanings, so it’s no longer clear what you are asking about.
user3840170
CC BY-SA 4.0
2023-11-20T19:34:23.490Z
Immutable local variables in a method often have different values in each invocation; personally I wouldn’t call that “constant”. And then there are read-only values that I cannot modify, but someone else can.
gnasher729
<p><a href="/a/3188">@apropos has covered most of this</a>, but I just thought I'd pick up on a point about terminology and add more detail.</p>
<p>A &quot;constant&quot; is typically a field (an area of computer memory treated conceptually by the programmer as a single unit of storage) whose value is assigned in source code and stored statically in the compiled executable file, with the value specified in source code either as a literal, or perhaps as a simple expression of other constants.</p>
<p>Storage for a constant is allocated statically (a space is reserved in the executable itself), and the value of a constant is loaded from the executable into main memory at the same time that the whole program is loaded into main memory by the operating system. This means the value of the constant is already set before the program begins running, and the value does not change for the lifetime of the running program.</p>
<p>A &quot;variable&quot; is a field whose value is assigned (and reassigned) at run-time by the program. Unlike constants, variables can be computed at run-time from inputs that wouldn't have been available at compile-time. Unlike constants, the storage for variables can also be allocated and deallocated dynamically - that is, variables can be allocated in main memory, but have no equivalent space already reserved in the executable as constants do.</p>
<p>An &quot;immutable variable&quot; is a term for a variable that is assigned only once by the program, typically at the site of declaration. That is, fundamentally it is a variable (in the variable/constant distinction described above), except only one initial assignment is allowed. This single-assignment is enforced by the compiler.</p>
<p>&quot;Immutable&quot; may have been a misnomer originally in the sense that there is a run-time mutation, although in usage the term &quot;immutable&quot; has come to mean &quot;mutable once only&quot;.</p>
<p>To confound things further, many languages allow variables to be initialised from literals stated in the source code, much like constants are initialised. In this case, what happens in practice is that an anonymous constant is created by the compiler to store the literal value in the executable, and then at run time the value of the anonymous constant is copied into the variable.</p>
<p>The essential difference between constants and immutable variables, is that constants have their values built at compile-time, whereas immutable variables have their values built at run time.</p>
<p>Constants are immutable across all executions of a particular compiled program, whereas immutable variables are only necessarily immutable for the lifetime of a single run of the program. You can start another run of the same program, and the value of the constant will be the same for both, but the value of the immutable variable may well differ.</p>
<p>Final thought: perhaps the word &quot;irremutable&quot; would have been a better term, capturing the idea that it is the ability to re-mutate which is excluded, not the ability to mutate at all.</p>

CC BY-SA 4.0
2023-11-19T13:46:04.057Z
2023-11-20T11:21:44.750Z
2023-11-20T11:21:44.750Z
Steve
CC BY-SA 4.0
2023-11-19T17:05:17.200Z
From a language perspective, an immutable value is _truly_ immutable: for the entire duration of its existence, its value does not change. Only at the implementation level can we see the memory in which this value is stored undergoing mutation during the initialization, but that's an implementation detail that languages do not concern themselves with (typically).
Matthieu M.
CC BY-SA 4.0
2023-11-19T19:47:34.530Z
@MatthieuM., even a "language perspective" would have to concern itself with the question of whether a value can change across program runs or not. An "immutable" variable can change across runs, because it can be set once each time it is declared; since a program can usually accept inputs before all declarations have occured, it is possible to alter the values of immutable variables by varying the program inputs. A constant doesn't vary across runs - it can only be altered in source code.
Steve
CC BY-SA 4.0
2023-11-20T04:38:37.390Z
@Steve It's not "the same variable" when a program runs multiple times, any more than it's "the same" local variable each time a function is called. (Local variables being distinct is hard to argue against, since the same function can have multiple overlapping invocations concurrently, which is inconsistent with a variable holding _one_ value at a time.)
Martin Kealey
CC BY-SA 4.0
2023-11-20T04:40:41.773Z
Initialising a variable does not count as "mutation" - changing from one value to another. There is no previous value, so no change. Thus I disagree with "irremutable"
Martin Kealey
CC BY-SA 4.0
2023-11-20T11:39:39.640Z
@MartinKealey, the very fact that it isn't the "same variable" on each run, is precisely what distinguishes variables from constants! As for initialising not counting as "mutation", I'm afraid that's an unsound perspective on the situation for anyone who understands computer science. The allocation of memory - defining the structure of storage which a program relies upon for its workings - is always fundamentally a different thing from assignment into that storage. The fact that some languages do both things in a one-liner, doesn't mean they become the same things.
Steve
CC BY-SA 4.0
2023-11-20T17:54:22.277Z
@Steve: A compiler processing an ordinary assignment must ensure that it is sequenced after any other operation that might modify the variable in question, even if the question of whether a particular action would modify the variable would be intractable.  A compiler processing an initialization would merely need to ensure that the action is sequenced after any  *compiler-generated* action that reserves space for it.
supercat
CC BY-SA 4.0
2023-11-21T10:03:25.363Z
@supercat, indeed, but just because you put handcuffs on the man doesn't mean he only has one arm. The fact that a particular language puts allocation and assignment in a particular fixed relationship, doesn't mean the distinction between those two things in general discourse has disappeared. The OP asked for the distinction between constants and immutable variables, in no particular language, and the answer is to be found in the difference in how (and when) they are allocated and assigned. (1/2)
Steve
CC BY-SA 4.0
2023-11-21T10:04:38.207Z
Also, the word "immutable" is used much more widely than just languages that have immutable variables enforced by the compiler. It may be applied to objects which have a constructor, mutable fields internally for storage, and read-only properties. The meaning is the same: it means the ability to set the variables once, but not again. It's an extremely common concept. In hardware it's called PROM - constants would be ROM. In databases it's called "insert-only". It's not some fancy new thing that some modern language designer only just invented - it appears frequently in many domains. (2/2)
Steve
CC BY-SA 4.0
2023-11-21T15:41:50.930Z
@Steve: My point is that a compiler that wants to perform the computations that initialize an object's value eagerly, e.g. because the initialization as written would occur in a loop, may perform the initialization as early as it wants if it ensures that the reservation of the storage--*which it controls*--occurs at least as early.  If within a loop a program writes something via an `int*` and then to a pre-existing `int`, a compiler could only hoist the write via `int` if it could prove that the write via `int*` didn't affect the same object.
supercat
CC BY-SA 4.0
2023-11-21T16:39:12.903Z
@supercat, surely in a language where declaration can be made separately from assignment, a compiler could still optimise if it happened to find the two operations together in sequence, and was able to determine that there weren't in fact subsequent assignments?
Steve
CC BY-SA 4.0
2023-11-21T17:10:57.767Z
@Steve: If people writing optimizing compilers focus on "low hanging fruit", they could have compiler that sees `int const y = x;, within a loop having previously see `int const x = something;` hoist the initialization/assignment out of the loop without the compiler having to know or care about whether any code takes the address of `x` or `y`.  If x` and `y` were ordinary objects set via ordinary assignment, a compiler would need to check whether their addresses were taken and, if so, scan extensively for any code that might access them via pointers.  A "low-hanging fruit" optimizer...
supercat
CC BY-SA 4.0
2023-11-21T17:13:02.407Z
...might, given a language where programmers use that form initialization when practical, sensibly be designed to refrain from trying to optimize ordinary assignments rather than perform the more extensive analysis required to do so in a manner that is soundly reliable.
supercat
<p>If it is a variable, regardless if immutable or not, you can get the <strong>address</strong> of it when needed (a language must support a concept of the pointer to immutable object for this to work safely). A compile time constant has no address.</p>
<p>An address of the immutable object can be used:</p>
<ul>
<li>For easy check if it is the same object.</li>
<li>For sharing the immutable object.</li>
<li>When using immutable pointers to &quot;user objects&quot; like tree data nodes.</li>
<li>When passing variables of various sizes and types as uniform list of addresses.</li>
</ul>
<p>In C++, constant references can be used to obtain the immutable address of otherwise mutable variable. This allows to track easier where the variable could probably be modified. For instance, some startup code may set the variable, and the most of the program only see a constant reference to it, making sure the variable cannot be modified any further.</p>

CC BY-SA 4.0
2023-11-20T18:53:58.770Z
2023-11-20T18:53:58.770Z
Audrius Meškauskas
CC BY-SA 4.0
2023-11-21T02:32:26.243Z
Other examples of immutable objects are the ones provided at a fixed address by CPUs, microcontrollers or other hardware in the system; they can, for instance, contain a serial number or calibration values (e.g. for an internal temperature sensor or voltage reference).
NZD
<p>This is an old question with many good answers but in a quick survey of them I think none mention a particularly important difference between constants and readonly variables.</p>
<p>In C#, named constants must <em>semantically</em> be constant, <em>forever</em>. Why is that?  Because the compilation model of C# <em>assumes</em> that constants are constant forever. Let me illustrate how this goes wrong.  Suppose you have two assemblies, Alpha.DLL and Bravo.DLL, where Bravo has a dependency on Alpha.  In the source code for Alpha, you somewhere have</p>
<pre><code>public const string AlphaCopyright = &quot;Alpha Software Copyright 2024&quot;;
</code></pre>
<p>If Bravo somewhere in it has</p>
<pre><code>Console.WriteLine(&quot;Bravo uses Alpha Corp software&quot;);
Console.WriteLine(Alpha.Whatever.AlphaCopyright);
</code></pre>
<p>then when Bravo is compiled, the compiler <strong>copies the constant value into Bravo.DLL</strong>. It does NOT generate code that looks up the value in Alpha.</p>
<p>Now suppose some user out there has a copy of Bravo.DLL and Alpha.DLL, but they update their version of Alpha.DLL to a version that has</p>
<pre><code>public const string AlphaCopyright = &quot;Alpha Software Copyright 2024-2025&quot;;
</code></pre>
<p>then when they run code in Bravo, it <em>still</em> has the original copyright notice from when it was compiled. It does not pick up the new one, even though from reading the source code, it looks like it should be picking up the latest from whatever version of Alpha is installed.</p>
<p>The compiler assumes that anything marked const will <em>never</em> change even in future versions of the source code, and optimizes accordingly, so if a value could possibly change at some point in the future then mark it as readonly, not as constant, or make it a readonly property. Alpha's developers should have declared this as a property, not a const.</p>

CC BY-SA 4.0
2024-06-19T16:58:23.120Z
2024-06-19T17:09:04.077Z
2024-06-19T17:09:04.077Z
Eric Lippert
CC BY-SA 4.0
2024-06-21T14:09:09.417Z
I wonder how much of it is language semantics and how much of it is DLL quirks. Even with C, you could have a header with a given value for a constant, and a DLL which was compiled with a prior value, and thus no longer match. To me, this indicates not a _semantic_ specificity of C, and more a "failure" of toolchain/distribution in not realizing the discrepancy between the two. Similarly, in your scenario, one could argue the failure is that `Bravo.DLL` was not properly updated when `Alpha.DLL` was...
Matthieu M.
CC BY-SA 4.0
2024-06-21T14:11:07.820Z
... For example, what if we shift to speaking about inline methods, rather than constants. If a method of `Alpha` was inlined in `Bravo.DLL`, and thus subsequently does not match that of `Alpha.DLL`, is it a developer issue because an inline method definition should never change? Or a toolchain/distribution issue because `Bravo.DLL` is not matching `Alpha.DLL`? I'd definitely argue that it's the latter.
Matthieu M.
CC BY-SA 4.0
2024-06-27T19:53:11.580Z
@MatthieuM.: Though I take your point, the C# compiler *never* inlines code when generating IL; calls are generated as calls. As you correctly note, it would cause versioning problems if code were inlined across assemblies, but the problem is more general than that: **the C# compiler has no basis upon which to decide whether inlining is an optimization or not!** The *jitter* makes that decision because the jitter knows what the performance characteristics of the hardware are.
Eric Lippert
<p>The different levels of const-ness are vital to lower levels of systems programming. The important distinction in systems programming between a compile time constant and an immutable variable relates to performance, the <em>programmer's intent</em>, and safety in the presence of external effects. Two prominent examples, Rust and C, make this distinction, and in more or less the same way.</p>
<h2>Actual compile-time constants (that definitely are)</h2>
<p>C has <code>#define</code>s that can effectively be considered direct textual substitution — copy and paste, if you like. Rust's <code>const</code>s are the same, except they're typed. It is useful to consider that <a href="https://doc.rust-lang.org/std/vec/struct.Vec.html#method.new" rel="nofollow noreferrer"><code>Vec::new()</code></a> is <code>const</code>!</p>
<p>Why is creating a dynamically growable array <code>const</code> though? Because a vec does not allocate when it's created. There are no runtime side effects at this point. The data structure that makes it up can be populated with the platform's equivalent of a null pointer and zero length entirely at compile time. This leads to confusion over this kind of code:</p>
<pre class="lang-rust prettyprint-override"><code>const CONST_VEC: Vec&lt;String&gt; = Vec::new();

pub fn main() {
    CONST_VEC.push(&quot;Hello&quot;.into());
    CONST_VEC.push(&quot;world!&quot;.into());
    dbg!(CONST_VEC);
}
</code></pre>
<p>The <a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2021&amp;gist=11b539977950260f62686426c7b1d7e9" rel="nofollow noreferrer">output of this</a> is:</p>
<pre class="lang-none prettyprint-override"><code>[src/main.rs:7] CONST_VEC = []
</code></pre>
<p>Why? Because this code effectively copy-pastes <code>Vec::new()</code> into <em>each place</em> where you see <code>CONST_VEC</code>. That's what a compile time constant is, a straight up substitution of compile-time-computable values. (You get warnings about this. Just to be clear. Rust knows you're doing something silly here.)</p>
<p>The point of this kind of copy-paste constant is simply to reduce repetition and document intent by naming, without compromising on the performance gains of static program parameters. Repetition of literals is bad because each repetition is the site for a potential mis-copy. Make the infallible machine do the copying! Naming is good, because identical literals may have different purposes, and a simple find-and-replace does not know that. Tell the fallible human which number to replace when a requirement changes!</p>
<h2>Immutable variables (that might not be)</h2>
<p>In a lot of cases, yes, there is no difference. Indeed in C++ a static <code>const</code> that is not also <code>volatile</code> can be treated the same as a <code>#define</code> or Rust <code>const</code> — a copy-paste. (Someone please correct me if I'm wrong, I'm not nearly as familiar with C++.)</p>
<p>But. In both Rust and C, their respective immutable variables <em>can change</em>, even within the lifetimes of the bindings. This is not some quirk or hackery, it is not unsafe, it is <em>by design</em>. The &quot;immutability&quot; is thus about what the programmer intends and declares, not the data itself.</p>
<p>In Rust, a non-<code>mut</code> variable can change due to <a href="https://doc.rust-lang.org/std/cell/index.html" rel="nofollow noreferrer"><em>interior mutability</em></a> eg. using one of the <a href="https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html" rel="nofollow noreferrer"><code>UnsafeCell</code></a>-derived types. You might regard this as a technicality or escape hatch, but interior mutability, and more importantly <em>safe</em> interior mutability, is a fundamental part of Rust's goal of combining usefulness and safety. <code>UnsafeCell</code> might expose an unsafe API, but there are plenty of <em>safe</em> interior mutability wrappers in Rust's stdlib eg. <a href="https://doc.rust-lang.org/std/cell/struct.RefCell.html" rel="nofollow noreferrer"><code>RefCell</code></a> and <a href="https://doc.rust-lang.org/std/sync/struct.Mutex.html" rel="nofollow noreferrer"><code>Mutex</code></a>.</p>
<p>In C, a <code>const volatile</code> variable is perfectly valid. What does it mean for a variable to be both <code>const</code> (&quot;does not change&quot;) and <code>volatile</code> (&quot;can change outside of operations known to the compiler&quot;)? One of those mental models must be wrong, and it's the first one. <code>const</code> simply means that the programmer, the human typing the word <code>const</code>, is declaring that <em>they</em> will not need to write code that directly changes it. The C compiler can enforce this. If the variable is not also <code>volatile</code>, the compiler can also make decisions about optimisations (reordering, combining, even total elision). If it <em>is</em> <code>volatile</code>, the compiler can only (but still) enforce the intent declared by the programmer.</p>
<p>Examples of where this commonly applies, in both languages:</p>
<ul>
<li>hardware exposed as a read-only memory-mapped peripheral eg. a UART receive buffer</li>
<li>data crossing foreign function interface (FFI) boundaries</li>
<li>data shared across thread or process boundaries.</li>
</ul>
<hr />
<p>Embedded and OS programming (for example) <em>depend</em> upon:</p>
<ul>
<li>having practical support from the language to simultaneously...
<ul>
<li>constrain what the programmer can mutate...</li>
<li>while accounting for the presence of externally driven side effects;</li>
</ul>
</li>
<li>achieving high performance by exploiting knowledge of program parameters</li>
</ul>
<p>Taking a higher view then, these different levels of <code>const</code>-ness exist because of the intersection of requirements that are especially common in (although not exclusive to) low-level applications.</p>

CC BY-SA 4.0
2023-11-21T03:17:30.457Z
2023-11-21T15:54:47.923Z
2023-11-21T15:54:47.923Z
detly
CC BY-SA 4.0
2023-11-21T14:15:51.673Z
What is FFI? [Foreign function interface](https://en.wikipedia.org/wiki/Foreign_function_interface)?
Peter Mortensen
CC BY-SA 4.0
2023-11-21T15:54:10.213Z
@PeterMortensen Yes! Sorry for the jargon, I should use the full term on first use.
detly
<p>In many programming languages, a <em>constant</em> refers exclusively to <strong>compile-time constants</strong>. C, C++, and JavaScript do not appear to make this distinction and instead use the keyword for immutable bindings, but it appears in Rust, Nim, C#, Go, Kotlin, Lean...</p>
<p>So yes, a run-time constant is just an immutable variable. And no, a compile-time constant is not the same as an immutable variable. While distinctions between mutable and immutable variables are quite important for both compilers and programmers, a compile-time constant has a fixed value in memory, known to the compiler, and so many more optimizations may be done with it.</p>
<p>Terminology issues abound in computer science and I do not doubt that many other languages I've missed refer to immutable variables as constants, but it does appear broadly much more common for them to refer to values known at compile-time. See also: the idea of <code>constexpr</code> (C++), <code>const exprs</code> (Rust), <code>comptime</code> (Zig), <code>static</code> (Nim)... also, quite funny to see C++ pick up <code>constexpr</code> for compile-time evaluated expressions, in contrast to <code>const</code>'s behavior in the language.</p>

CC BY-SA 4.0
2023-11-19T10:19:25.873Z
2023-11-19T10:19:25.873Z
apropos
CC BY-SA 4.0
2023-11-19T17:37:20.890Z
Scala has a notion of *constant expressions* for a similar construct. It is less like a language feature and more like language-mandated optimization: any field that is explicitly marked as `private final`, is not annotated with an explicit type, and is initialized with a literal expression, is guaranteed to always be inlined.
Jörg W Mittag
CC BY-SA 4.0
2023-11-20T04:17:14.707Z
C & C++ certainly _do_ have compile-time constants, but they don't mark them by using `const`; rather they mark them using `enum` or `#define` or `&static_variable_name` or `&function_name`. (Instead, `const` denotes immutability.)
Martin Kealey
CC BY-SA 4.0
2023-11-20T05:31:36.127Z
@MartinKealey All of those approaches have drawbacks, I believe: `#define` loses type information, `enum` only works for integers (and loses type information), and I'm not quite sure what the `&` prefix denotes.
apropos
CC BY-SA 4.0
2023-11-20T08:59:42.670Z
@apropos `&` is taking the address. Macros don't lose type information, they're just fancy copy-and-paste on your source code and a hugely problematic construct in many ways.
Passer By
CC BY-SA 4.0
2023-11-20T12:37:05.740Z
@PasserBy Since they are just text copied into the code they lose type information
mousetail 'he-him'
CC BY-SA 4.0
2023-11-20T13:14:19.980Z
I think C++'s "funny" laissez-faire approach to the distinction here is due to its "as if" rule. A C++ compiler is perfectly free to optimize out at compile time anything it doesn't need to have memory storage for (even non-marked "regular" variables!), and any compiler which doesn't do that for blatantly obvious cases is a bad compiler. So labeling in C++ is less about micromanaging compiler decisions, and more about giving the compiler enough information that it can do the best job of optimizing that it can..
R.M.
CC BY-SA 4.0
2023-11-20T15:03:49.980Z
@mousetail With `#define PI 3.14`, `PI` is a `double`. How is that losing type information or any different than, say, `constexpr double pi = 3.14;`?
Passer By
CC BY-SA 4.0
2023-11-20T15:04:37.367Z
@PasserBy If you `#define PI 3` it could be a int, short, float, long, unsigned char...
mousetail 'he-him'
CC BY-SA 4.0
2023-11-20T15:05:02.000Z
@mousetail It's not. If you did that, `PI` is an `int`.
Passer By
CC BY-SA 4.0
2023-11-20T15:22:45.990Z
@MartinKealey *C & C++  ... `const` denotes immutability*  IMO in C `const` is better characterized as "read-only, or else UB" per the wording of [(draft) C11 6.7.3p3](https://port70.net/~nsz/c/c11/n1570.html#6.7.3p6).  There's even [a `const volatile` example in the standard](https://port70.net/~nsz/c/c11/n1570.html#6.7.3p11).  `volatile` certainly implies anything but immutable.
Andrew Henle
CC BY-SA 4.0
2023-11-21T03:35:44.047Z
@PasserBy `PI` is just some text. If you use it like `auto foo = PI`, then foo is an int. If you use it like `auto foo = PI.14`, then foo is a double.
Ethan B.
CC BY-SA 4.0
2023-11-21T04:26:12.900Z
@EthanB. That won't compile, so no, it's not.
Passer By
CC BY-SA 4.0
2023-11-21T10:52:01.430Z
@MartinKealey: You're right for C, but C++ has constexpr as well. That is a true compile-time typed constant (has to be, because C++ templates are compile time, and those accept constexpr arguments).
MSalters
CC BY-SA 4.0
2023-11-22T03:40:09.987Z
@AndrewHenle agreed; `const` only means it cannot be changed through this declaration, it does not mean nothing else can change it. So "immutable" is an overstatement.
Martin Kealey
CC BY-SA 4.0
2023-11-22T05:30:43.987Z
@PasserBy Huh, you're right. I didn't realize that macro expansion replaces identifiers rather than just any instance of the text (though it seems obvious in hindsight). Maybe should've taken that compilers class sometime...
Ethan B.
<h2>Why Have Different Syntax?</h2>
<p>I think it's safe to say that, in general, languages make syntactic distinctions like this when</p>
<ol>
<li>a compiler could not (reasonably) determine which option to use without the distinction, but no option is an acceptable default; or when</li>
<li>the language wants the programmer to <em>positively</em> opt into an option, because there are consequences.</li>
</ol>
<p>In the case of immutable variables versus constants, I'd say it's a bit of both.</p>
<h3>Immutable Variables and Constants</h3>
<p>Immutable variables and constants are very similar, and some languages are happy to treat them as the same thing. I think, at least in the context of this question, we should differentiate them.</p>
<p>An immutable variable is simply a variable (a name referring to storage) that is immutable, by which we mean assigned at most once (or exactly once, depending on the language) at run time. This frees the compiler to make assumptions about the variable—for example, once the variable is assigned, the compiler can copy its value without worrying about synchronization.</p>
<p>A constant is one step further: it's a name referring to a static value, known at compile time. They don't necessarily refer to any storage—often the compiler just inlines their value into every expression that references them  (depending on the language and compiler).</p>
<h3>Different Syntax Because the Compiler Can't Decide</h3>
<p>As I said, some languages are happy with one syntax for both immutable variables and constants. These languages may fall back to an immutable variable if the compiler can't determine that it could use a constant, or they may not have a concept of constants (as we've defined them) at all. Some languages, on the other hand, require separate syntax because it's not acceptable to default one way or the other.</p>
<p>One key difference between the two, in languages with pointers or references, is that immutable variables <em>must</em> refer to storage, and so have a defined address. On the other hand, constants need not refer to storage—depending on the language, constants may not have a defined address at all (as with C and C++ preprocessor constants), or their address may refer to a temporary copy and be different for each reference (as with Rust constants).</p>
<p>Also, since constants may be inlined, it may not be possible to recover their value at run time—e.g., for dynamic linking. There's not necessarily a variable to read, and if the language doesn't offer reflection the value may have been erased entirely during compilation.</p>
<p>Given these differences, it would never really be safe for the compiler to choose to use a constant for any public symbol. It would be disastrous if the compiler <em>inconsistently</em> chose to use a constant, because there would be observable differences in behavior and in ABI depending on the choice. But even if the compiler consistently chose to use a constant, it couldn't know if modules linking against this one would need to take references to the potential immutable variable, or read its value.</p>
<p>But it's also not acceptable for these languages to give up the ability to define constants—they're a very useful and common optimization. So, the language makes the programmer choose.</p>
<h3>Different Syntax to Make the Programmer Positively Opt In</h3>
<p>A language may also want a programmer to <em>positively</em> opt in to using a constant. Constants are generally more restrictive than immutable variables, since constants' values must be known at compile time. So the language makes the programmer intentionally choose one way or the other, even if the language could potentially make good automatic choices in some cases.</p>
<p>Imagine a language that has a single syntax to define immutable variables and constants, where the compiler uses a constant when it could determine the initializer's value at compile time, and creates an immutable variable otherwise. We might start out with a simple, obvious constant like</p>
<pre><code># Made up syntax...
const var FOO = 3
</code></pre>
<p>But this might evolve. It might get changed later to</p>
<pre><code>const var FOO = 3 * 1000
</code></pre>
<p>Is this still a constant? It depends whether this language supports multiplication in constant expressions—many do, but if not then <code>FOO</code> just switched to an immutable variable. (And if multiplication is allowed, what about a function call?) If we're lucky, our change would lead to compilation errors or failed tests elsewhere in the module. But if not, there may not be any indication we changed something until we start receiving bug reports from downstream projects that link against ours.</p>
<p>Things would get especially tricky if the language also offered user-defined constant functions (such as C++ <code>constexpr</code>s and Rust <code>const fn</code>s), where a function could change from constant to non-constant and turn constants into immutable variables at a distance (or vice versa).</p>
<p>So instead, languages where the distinction matters tend to use separate syntax for declaring immutable variables and constants. Once the programmer has opted into one or the other, the compiler can preserve the programmer's stated <em>intention</em>—raising errors for misuse if necessary.</p>

CC BY-SA 4.0
2023-11-20T01:56:57.960Z
2023-11-20T01:56:57.960Z
Chris Bouchard
CC BY-SA 4.0
2024-08-29T10:37:00.470Z
In my opion, this is the answer that is most suitable from a compiler and language *design* perspective and is the most suitable for this section of stackexchnage.
m0h4mm4d
<p>A constant is a variable whose value cannot change <em>at all</em>, whereas an immutable variable is a variable whose value cannot change <strong>for the lifetime of the variable</strong>, i.e. while the variable is in scope, but the value can be different between different lifetimes.</p>
<p>Consider the following Rust example:</p>
<pre class="lang-rust prettyprint-override"><code>const FOO: usize = 5;

fn bar(x: usize) -&gt; usize {
    let y = x + 5;
    y * 2
}

fn main() {
    println!(&quot;{}&quot;, FOO);
    println!(&quot;{}&quot;, bar(6));
    println!(&quot;{}&quot;, bar(7));
}
</code></pre>
<p>In this example, <code>FOO</code> is a constant, since its value can never change at any point during program execution. On the other hand, <code>y</code> is an immutable local variable, whose value cannot change within a single activation of the function <code>bar</code>. But <code>y</code> can have different values at different times ─ in this program, it takes the values 11 and 12. Likewise, <code>x</code> is an immutable variable taking the values 6 and 7.</p>
<p><sup>Note that the use of the word &quot;lifetime&quot; above does correspond with lifetimes in Rust's ownership model, but the same would apply in any other language.</sup></p>

CC BY-SA 4.0
2023-11-19T12:22:58.797Z
2023-11-19T12:22:58.797Z
kaya3
CC BY-SA 4.0
2023-11-19T20:26:34.653Z
You write "*during program execution*", but that sounds also like a lifetime to me. What about variables that never change during program execution, but might have different values in different executions (e.g. `argc` and `argv`, or something initialised from an environment variable), would you consider those to be "constants" as well?
Bergi
CC BY-SA 4.0
2023-11-19T20:33:29.207Z
I'd phrase it as "*its value is fixed for this whole program*". Using a different value requires changing the program code, i.e. using a different program.
Bergi
CC BY-SA 4.0
2023-11-19T20:42:30.483Z
@Bergi Using a different value for a constant doesn't necessarily require changing the program code, for example it could depend on the size of some type on the target architecture, and hence have different values when compiled for different targets. There are different uses of terms like this, so in some contexts "constant" may mean what you describe, but my usage of the term is consistent with [Wikipedia's](https://en.wikipedia.org/wiki/Constant_(computer_programming)): *"a value that should not be altered by the program during normal execution"*.
kaya3
CC BY-SA 4.0
2023-11-19T20:43:31.090Z
I think Wikipedia's definition is broader ("should not" vs. "cannot") so as to include "constants" in languages like Python which don't enforce their unchanging-ness at the language level.
kaya3
CC BY-SA 4.0
2023-11-19T20:47:40.083Z
I meant changing the *program*, i.e. the executed code, not necessarily changing the source code. Compiling it with different settings also creates a different program. But thanks for your clarifications, I understand what you mean now. A constant is, according to you, a global/static/top-level immutable variable.
Bergi
CC BY-SA 4.0
2023-11-19T20:50:06.143Z
@Bergi That's assuming the program is compiled at all; a constant in an interpreted language could change due to a change in the interpreter, and would that create a different program? I'll leave that question to the philosophers. I'll add that global/static immutable variables aren't always necessarily constants, e.g. a `static final` variable in Java can in some circumstances be observed before its assignment, in which case it will have the default initial value for its type.
kaya3
CC BY-SA 4.0
2023-11-19T21:05:27.863Z
A change in the interpreter would be an altered programming language with different semantics :-) Or less drastic, those constant values provided by the runtime would need to be considered input to the execution of the program.
Bergi
CC BY-SA 4.0
2023-11-19T21:05:57.260Z
Btw I'll change Wikipedia's definition from "should not change" to "does not change", that seems way more sensible. It actually [said "can not change" until 2021](https://en.wikipedia.org/w/index.php?title=Constant_(computer_programming)&diff=prev&oldid=1009693519)
Bergi
CC BY-SA 4.0
2023-11-20T08:54:49.277Z
It's worth pointing out that in both Rust and C, their respective immutable variables _can_ change, even within the lifetimes of the bindings. In Rust, a non-`mut` variable can change due to interior mutability eg. using one of the [`UnsafeCell`](https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html)-derived types. In C, a `const volatile` variable is perfectly valid. In both cases, this might (for example) relate to a read-only memory-mapped peripheral, or data managed via FFI. And in both cases, the "immutability" is about what the programmer of that code, in that language, agrees to.
detly
CC BY-SA 4.0
2023-11-20T17:58:08.207Z
@detly That's true, some languages have "escape hatches" like `unsafe`, reflection, etc. which might allow otherwise-immutable variables to change. I don't think this changes what the concepts of "constant" or "immutable variable" mean, though, rather this implies that the language constructs don't strictly adhere to those concepts. There's also the more mundane case where an immutable variable of reference type points to a mutable object, where semantically the reference itself doesn't change, but for practical purposes you might not care that it is a reference.
kaya3
CC BY-SA 4.0
2023-11-20T20:52:00.337Z
"A constant is a variable." There is something very wrong with this phrase and I hate the fact that some programmers somehow make sense of it. The two words are literal opposites of each other.
Longinus
CC BY-SA 4.0
2023-11-20T23:07:34.680Z
@Longinus *"In computer programming, a [variable](https://en.wikipedia.org/wiki/Variable_(computer_science)) is an abstract storage location paired with an associated symbolic name, which contains some known or unknown quantity of data or object referred to as a value"*. No need for the value stored in that location to actually vary; blame programmers if you like, but also *"In mathematics, a [variable](https://en.wikipedia.org/wiki/Variable_(mathematics)) ... is a symbol that represents a mathematical object"* with likewise no requirement that the object represented by the symbol must vary.
kaya3
CC BY-SA 4.0
2023-11-20T23:35:32.210Z
@kaya3 A variable _can_ change at any point. If a constant "was a variable" then the expectation of π not changing tomorrow morning at 4:20 UTC+1 could not be held. Same reason why C's "const pointers" are called "read-only" in other (better) nomenclatures. Also why a Square can never be a subclass of a mutable Rectangle.
Longinus
CC BY-SA 4.0
2023-11-20T23:41:22.673Z
@Longinus That's fallacious, like saying "a worker can be fired at any point, somebody self-employed cannot be fired, therefore somebody self-employed is not a worker". The possibility of being fired is not a definition of a worker, it is just a property which is generally true of workers. Likewise, the possibility of changing in value is a property which is generally true of variables, but it is not a definition of a variable; you can see that in the definitions I quoted, neither in programming nor in mathematics are variables defined as necessarily being able to change in value.
kaya3
CC BY-SA 4.0
2023-11-20T23:45:23.637Z
@kaya3 A worker who can be fired is an employee. Also [Cambridge Dictionary](https://dictionary.cambridge.org/dictionary/english/variable) and [Merriam-Webster](https://www.merriam-webster.com/dictionary/variable) both agree on mutability (or, rather, abstracting one of many values) being an essential part of the definition.
Longinus
CC BY-SA 4.0
2023-11-20T23:49:42.510Z
@Longinus *"a letter or symbol that represents any of a set of values"*, *"a quantity that may assume any one of a set of values; a symbol representing a variable"* ─ doesn't even mention mutability. Perhaps you are looking at the adjective instead of the noun? Not that I would choose any general-purpose dictionary as an authority on the specific meaning of a word in mathematics or programming (Wikipedia is actually very accurate for those subjects), but they're the sources you chose, so... :shrug:
kaya3
CC BY-SA 4.0
2023-11-21T00:26:53.250Z
@kaya3 Right, mutation is variance over time. An abuse of language on my part @_@ Anyway, given the several existing nomenclatures (i imagine some distinguish between variables and _lvalues_ too (with only the latter defined in terms of storage)), I guess this conversation p much relies on personal preferences as far as pldev goes. [Those maths.SO answers explain my preferred understanding better than I can, if it's of any interest](https://math.stackexchange.com/questions/859288/variable-vs-constant).
Longinus
# Why do some languages have both immutable "variables" and constants?
Posted by: username_0 on 2023-11-19
Some programming languages (Rust is one I can think of off the top of my head) provides mechanisms to have immutable variables but they also have constants. Isn't an immutable variable just a constant? What advantage is there in supporting both?
**Tags:** variables immutable
> **Comments:**
> **username_1**: Maybe provide some reasoning on why an immutable variable is a constant? You might be able to find some differences.  
> **username_2**: Is this question about Rust, or about immutabile and constant variables in general? Rust uses *very specific* meanings of both of these terms that are not universal, and an answer that addresses either Rust or the broader case isn’t going to do a good job of the other (in fact, likely be contradictory!). How general is this question intending to be?  
> **username_3**: If it's not about Rust: an immutable variable still has a location and lifetime, a constant just is.  
> **username_0**: I decided to remove the "rust" tag since this question isn't specifically about Rust and I was just using that as one example.  
> **username_4**: @QAH But in a different language those terms may have different meanings, so it’s no longer clear what you are asking about.  
> **username_5**: Immutable local variables in a method often have different values in each invocation; personally I wouldn’t call that “constant”. And then there are read-only values that I cannot modify, but someone else can.  
---
## 7 answers
### Answer by username_15 on 2023-11-19. Score: 32 | Accepted answer
In many programming languages, a *constant* refers exclusively to **compile-time constants**. C, C++, and JavaScript do not appear to make this distinction and instead use the keyword for immutable bindings, but it appears in Rust, Nim, C#, Go, Kotlin, Lean...

So yes, a run-time constant is just an immutable variable. And no, a compile-time constant is not the same as an immutable variable. While distinctions between mutable and immutable variables are quite important for both compilers and programmers, a compile-time constant has a fixed value in memory, known to the compiler, and so many more optimizations may be done with it.

Terminology issues abound in computer science and I do not doubt that many other languages I've missed refer to immutable variables as constants, but it does appear broadly much more common for them to refer to values known at compile-time. See also: the idea of `constexpr` (C++), `const exprs` (Rust), `comptime` (Zig), `static` (Nim)... also, quite funny to see C++ pick up `constexpr` for compile-time evaluated expressions, in contrast to `const`'s behavior in the language.
> **Comments:**
> **username_16** (2023-11-19): Scala has a notion of *constant expressions* for a similar construct. It is less like a language feature and more like language-mandated optimization: any field that is explicitly marked as `private final`, is not annotated with an explicit type, and is initialized with a literal expression, is guaranteed to always be inlined.  
> **username_8** (2023-11-20): C & C++ certainly _do_ have compile-time constants, but they don't mark them by using `const`; rather they mark them using `enum` or `#define` or `&static_variable_name` or `&function_name`. (Instead, `const` denotes immutability.)  
> **username_15** (2023-11-20): @MartinKealey All of those approaches have drawbacks, I believe: `#define` loses type information, `enum` only works for integers (and loses type information), and I'm not quite sure what the `&` prefix denotes.  
> **username_17** (2023-11-20): @apropos `&` is taking the address. Macros don't lose type information, they're just fancy copy-and-paste on your source code and a hugely problematic construct in many ways.  
> **username_18** (2023-11-20): @PasserBy Since they are just text copied into the code they lose type information  
> **username_19** (2023-11-20): I think C++'s "funny" laissez-faire approach to the distinction here is due to its "as if" rule. A C++ compiler is perfectly free to optimize out at compile time anything it doesn't need to have memory storage for (even non-marked "regular" variables!), and any compiler which doesn't do that for blatantly obvious cases is a bad compiler. So labeling in C++ is less about micromanaging compiler decisions, and more about giving the compiler enough information that it can do the best job of optimizing that it can..  
> **username_17** (2023-11-20): @mousetail With `#define PI 3.14`, `PI` is a `double`. How is that losing type information or any different than, say, `constexpr double pi = 3.14;`?  
> **username_18** (2023-11-20): @PasserBy If you `#define PI 3` it could be a int, short, float, long, unsigned char...  
> **username_17** (2023-11-20): @mousetail It's not. If you did that, `PI` is an `int`.  
> **username_20** (2023-11-20): @MartinKealey *C & C++  ... `const` denotes immutability*  IMO in C `const` is better characterized as "read-only, or else UB" per the wording of [(draft) C11 6.7.3p3](https://port70.net/~nsz/c/c11/n1570.html#6.7.3p6).  There's even [a `const volatile` example in the standard](https://port70.net/~nsz/c/c11/n1570.html#6.7.3p11).  `volatile` certainly implies anything but immutable.  
> **username_21** (2023-11-21): @PasserBy `PI` is just some text. If you use it like `auto foo = PI`, then foo is an int. If you use it like `auto foo = PI.14`, then foo is a double.  
> **username_17** (2023-11-21): @EthanB. That won't compile, so no, it's not.  
> **username_22** (2023-11-21): @MartinKealey: You're right for C, but C++ has constexpr as well. That is a true compile-time typed constant (has to be, because C++ templates are compile time, and those accept constexpr arguments).  
> **username_8** (2023-11-22): @AndrewHenle agreed; `const` only means it cannot be changed through this declaration, it does not mean nothing else can change it. So "immutable" is an overstatement.  
> **username_21** (2023-11-22): @PasserBy Huh, you're right. I didn't realize that macro expansion replaces identifiers rather than just any instance of the text (though it seems obvious in hindsight). Maybe should've taken that compilers class sometime...  
---
### Answer by username_25 on 2023-11-19. Score: 21
A constant is a variable whose value cannot change at all, whereas an immutable variable is a variable whose value cannot change for the lifetime of the variable, i.e. while the variable is in scope, but the value can be different between different lifetimes.
Consider the following Rust example:
const FOO: usize = 5;

fn bar(x: usize) -> usize {
    let y = x + 5;
    y * 2
}

fn main() {
    println!("{}", FOO);
    println!("{}", bar(6));
    println!("{}", bar(7));
}

In this example, FOO is a constant, since its value can never change at any point during program execution. On the other hand, y is an immutable local variable, whose value cannot change within a single activation of the function bar. But y can have different values at different times ─ in this program, it takes the values 11 and 12. Likewise, x is an immutable variable taking the values 6 and 7.
Note that the use of the word "lifetime" above does correspond with lifetimes in Rust's ownership model, but the same would apply in any other language.
> **Comments:**
> **username_26** (2023-11-19): You write "*during program execution*", but that sounds also like a lifetime to me. What about variables that never change during program execution, but might have different values in different executions (e.g. `argc` and `argv`, or something initialised from an environment variable), would you consider those to be "constants" as well?  
> **username_26** (2023-11-19): I'd phrase it as "*its value is fixed for this whole program*". Using a different value requires changing the program code, i.e. using a different program.  
> **username_25** (2023-11-19): @Bergi Using a different value for a constant doesn't necessarily require changing the program code, for example it could depend on the size of some type on the target architecture, and hence have different values when compiled for different targets. There are different uses of terms like this, so in some contexts "constant" may mean what you describe, but my usage of the term is consistent with [Wikipedia's](https://en.wikipedia.org/wiki/Constant_(computer_programming)): *"a value that should not be altered by the program during normal execution"*.  
> **username_25** (2023-11-19): I think Wikipedia's definition is broader ("should not" vs. "cannot") so as to include "constants" in languages like Python which don't enforce their unchanging-ness at the language level.  
> **username_26** (2023-11-19): I meant changing the *program*, i.e. the executed code, not necessarily changing the source code. Compiling it with different settings also creates a different program. But thanks for your clarifications, I understand what you mean now. A constant is, according to you, a global/static/top-level immutable variable.  
> **username_25** (2023-11-19): @Bergi That's assuming the program is compiled at all; a constant in an interpreted language could change due to a change in the interpreter, and would that create a different program? I'll leave that question to the philosophers. I'll add that global/static immutable variables aren't always necessarily constants, e.g. a `static final` variable in Java can in some circumstances be observed before its assignment, in which case it will have the default initial value for its type.  
> **username_26** (2023-11-19): A change in the interpreter would be an altered programming language with different semantics :-) Or less drastic, those constant values provided by the runtime would need to be considered input to the execution of the program.  
> **username_26** (2023-11-19): Btw I'll change Wikipedia's definition from "should not change" to "does not change", that seems way more sensible. It actually [said "can not change" until 2021](https://en.wikipedia.org/w/index.php?title=Constant_(computer_programming)&diff=prev&oldid=1009693519)  
> **username_13** (2023-11-20): It's worth pointing out that in both Rust and C, their respective immutable variables _can_ change, even within the lifetimes of the bindings. In Rust, a non-`mut` variable can change due to interior mutability eg. using one of the [`UnsafeCell`](https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html)-derived types. In C, a `const volatile` variable is perfectly valid. In both cases, this might (for example) relate to a read-only memory-mapped peripheral, or data managed via FFI. And in both cases, the "immutability" is about what the programmer of that code, in that language, agrees to.  
> **username_25** (2023-11-20): @detly That's true, some languages have "escape hatches" like `unsafe`, reflection, etc. which might allow otherwise-immutable variables to change. I don't think this changes what the concepts of "constant" or "immutable variable" mean, though, rather this implies that the language constructs don't strictly adhere to those concepts. There's also the more mundane case where an immutable variable of reference type points to a mutable object, where semantically the reference itself doesn't change, but for practical purposes you might not care that it is a reference.  
> **username_27** (2023-11-20): "A constant is a variable." There is something very wrong with this phrase and I hate the fact that some programmers somehow make sense of it. The two words are literal opposites of each other.  
> **username_25** (2023-11-20): @Longinus *"In computer programming, a [variable](https://en.wikipedia.org/wiki/Variable_(computer_science)) is an abstract storage location paired with an associated symbolic name, which contains some known or unknown quantity of data or object referred to as a value"*. No need for the value stored in that location to actually vary; blame programmers if you like, but also *"In mathematics, a [variable](https://en.wikipedia.org/wiki/Variable_(mathematics)) ... is a symbol that represents a mathematical object"* with likewise no requirement that the object represented by the symbol must vary.  
> **username_27** (2023-11-20): @kaya3 A variable _can_ change at any point. If a constant "was a variable" then the expectation of π not changing tomorrow morning at 4:20 UTC+1 could not be held. Same reason why C's "const pointers" are called "read-only" in other (better) nomenclatures. Also why a Square can never be a subclass of a mutable Rectangle.  
> **username_25** (2023-11-20): @Longinus That's fallacious, like saying "a worker can be fired at any point, somebody self-employed cannot be fired, therefore somebody self-employed is not a worker". The possibility of being fired is not a definition of a worker, it is just a property which is generally true of workers. Likewise, the possibility of changing in value is a property which is generally true of variables, but it is not a definition of a variable; you can see that in the definitions I quoted, neither in programming nor in mathematics are variables defined as necessarily being able to change in value.  
> **username_27** (2023-11-20): @kaya3 A worker who can be fired is an employee. Also [Cambridge Dictionary](https://dictionary.cambridge.org/dictionary/english/variable) and [Merriam-Webster](https://www.merriam-webster.com/dictionary/variable) both agree on mutability (or, rather, abstracting one of many values) being an essential part of the definition.  
> **username_25** (2023-11-20): @Longinus *"a letter or symbol that represents any of a set of values"*, *"a quantity that may assume any one of a set of values; a symbol representing a variable"* ─ doesn't even mention mutability. Perhaps you are looking at the adjective instead of the noun? Not that I would choose any general-purpose dictionary as an authority on the specific meaning of a word in mathematics or programming (Wikipedia is actually very accurate for those subjects), but they're the sources you chose, so... :shrug:  
> **username_27** (2023-11-21): @kaya3 Right, mutation is variance over time. An abuse of language on my part @_@ Anyway, given the several existing nomenclatures (i imagine some distinguish between variables and _lvalues_ too (with only the latter defined in terms of storage)), I guess this conversation p much relies on personal preferences as far as pldev goes. [Those maths.SO answers explain my preferred understanding better than I can, if it's of any interest](https://math.stackexchange.com/questions/859288/variable-vs-constant).  
---
### Answer by username_23 on 2023-11-20. Score: 10
Why Have Different Syntax?
I think it's safe to say that, in general, languages make syntactic distinctions like this when

a compiler could not (reasonably) determine which option to use without the distinction, but no option is an acceptable default; or when
the language wants the programmer to positively opt into an option, because there are consequences.

In the case of immutable variables versus constants, I'd say it's a bit of both.
Immutable Variables and Constants
Immutable variables and constants are very similar, and some languages are happy to treat them as the same thing. I think, at least in the context of this question, we should differentiate them.
An immutable variable is simply a variable (a name referring to storage) that is immutable, by which we mean assigned at most once (or exactly once, depending on the language) at run time. This frees the compiler to make assumptions about the variable—for example, once the variable is assigned, the compiler can copy its value without worrying about synchronization.
A constant is one step further: it's a name referring to a static value, known at compile time. They don't necessarily refer to any storage—often the compiler just inlines their value into every expression that references them  (depending on the language and compiler).
Different Syntax Because the Compiler Can't Decide
As I said, some languages are happy with one syntax for both immutable variables and constants. These languages may fall back to an immutable variable if the compiler can't determine that it could use a constant, or they may not have a concept of constants (as we've defined them) at all. Some languages, on the other hand, require separate syntax because it's not acceptable to default one way or the other.
One key difference between the two, in languages with pointers or references, is that immutable variables must refer to storage, and so have a defined address. On the other hand, constants need not refer to storage—depending on the language, constants may not have a defined address at all (as with C and C++ preprocessor constants), or their address may refer to a temporary copy and be different for each reference (as with Rust constants).
Also, since constants may be inlined, it may not be possible to recover their value at run time—e.g., for dynamic linking. There's not necessarily a variable to read, and if the language doesn't offer reflection the value may have been erased entirely during compilation.
Given these differences, it would never really be safe for the compiler to choose to use a constant for any public symbol. It would be disastrous if the compiler inconsistently chose to use a constant, because there would be observable differences in behavior and in ABI depending on the choice. But even if the compiler consistently chose to use a constant, it couldn't know if modules linking against this one would need to take references to the potential immutable variable, or read its value.
But it's also not acceptable for these languages to give up the ability to define constants—they're a very useful and common optimization. So, the language makes the programmer choose.
Different Syntax to Make the Programmer Positively Opt In
A language may also want a programmer to positively opt in to using a constant. Constants are generally more restrictive than immutable variables, since constants' values must be known at compile time. So the language makes the programmer intentionally choose one way or the other, even if the language could potentially make good automatic choices in some cases.
Imagine a language that has a single syntax to define immutable variables and constants, where the compiler uses a constant when it could determine the initializer's value at compile time, and creates an immutable variable otherwise. We might start out with a simple, obvious constant like
# Made up syntax...
const var FOO = 3

But this might evolve. It might get changed later to
const var FOO = 3 * 1000

Is this still a constant? It depends whether this language supports multiplication in constant expressions—many do, but if not then FOO just switched to an immutable variable. (And if multiplication is allowed, what about a function call?) If we're lucky, our change would lead to compilation errors or failed tests elsewhere in the module. But if not, there may not be any indication we changed something until we start receiving bug reports from downstream projects that link against ours.
Things would get especially tricky if the language also offered user-defined constant functions (such as C++ constexprs and Rust const fns), where a function could change from constant to non-constant and turn constants into immutable variables at a distance (or vice versa).
So instead, languages where the distinction matters tend to use separate syntax for declaring immutable variables and constants. Once the programmer has opted into one or the other, the compiler can preserve the programmer's stated intention—raising errors for misuse if necessary.
> **Comments:**
> **username_24** (2024-08-29): In my opion, this is the answer that is most suitable from a compiler and language *design* perspective and is the most suitable for this section of stackexchnage.  
---
### Answer by username_6 on 2023-11-19. Score: 3
[@apropos has covered most of this](/a/3188), but I just thought I'd pick up on a point about terminology and add more detail.

A "constant" is typically a field (an area of computer memory treated conceptually by the programmer as a single unit of storage) whose value is assigned in source code and stored statically in the compiled executable file, with the value specified in source code either as a literal, or perhaps as a simple expression of other constants.

Storage for a constant is allocated statically (a space is reserved in the executable itself), and the value of a constant is loaded from the executable into main memory at the same time that the whole program is loaded into main memory by the operating system. This means the value of the constant is already set before the program begins running, and the value does not change for the lifetime of the running program.

A "variable" is a field whose value is assigned (and reassigned) at run-time by the program. Unlike constants, variables can be computed at run-time from inputs that wouldn't have been available at compile-time. Unlike constants, the storage for variables can also be allocated and deallocated dynamically - that is, variables can be allocated in main memory, but have no equivalent space already reserved in the executable as constants do.

An "immutable variable" is a term for a variable that is assigned only once by the program, typically at the site of declaration. That is, fundamentally it is a variable (in the variable/constant distinction described above), except only one initial assignment is allowed. This single-assignment is enforced by the compiler.

"Immutable" may have been a misnomer originally in the sense that there is a run-time mutation, although in usage the term "immutable" has come to mean "mutable once only".

To confound things further, many languages allow variables to be initialised from literals stated in the source code, much like constants are initialised. In this case, what happens in practice is that an anonymous constant is created by the compiler to store the literal value in the executable, and then at run time the value of the anonymous constant is copied into the variable.

The essential difference between constants and immutable variables, is that constants have their values built at compile-time, whereas immutable variables have their values built at run time.

Constants are immutable across all executions of a particular compiled program, whereas immutable variables are only necessarily immutable for the lifetime of a single run of the program. You can start another run of the same program, and the value of the constant will be the same for both, but the value of the immutable variable may well differ.

Final thought: perhaps the word "irremutable" would have been a better term, capturing the idea that it is the ability to re-mutate which is excluded, not the ability to mutate at all.
> **Comments:**
> **username_7** (2023-11-19): From a language perspective, an immutable value is _truly_ immutable: for the entire duration of its existence, its value does not change. Only at the implementation level can we see the memory in which this value is stored undergoing mutation during the initialization, but that's an implementation detail that languages do not concern themselves with (typically).  
> **username_6** (2023-11-19): @MatthieuM., even a "language perspective" would have to concern itself with the question of whether a value can change across program runs or not. An "immutable" variable can change across runs, because it can be set once each time it is declared; since a program can usually accept inputs before all declarations have occured, it is possible to alter the values of immutable variables by varying the program inputs. A constant doesn't vary across runs - it can only be altered in source code.  
> **username_8** (2023-11-20): @Steve It's not "the same variable" when a program runs multiple times, any more than it's "the same" local variable each time a function is called. (Local variables being distinct is hard to argue against, since the same function can have multiple overlapping invocations concurrently, which is inconsistent with a variable holding _one_ value at a time.)  
> **username_8** (2023-11-20): Initialising a variable does not count as "mutation" - changing from one value to another. There is no previous value, so no change. Thus I disagree with "irremutable"  
> **username_6** (2023-11-20): @MartinKealey, the very fact that it isn't the "same variable" on each run, is precisely what distinguishes variables from constants! As for initialising not counting as "mutation", I'm afraid that's an unsound perspective on the situation for anyone who understands computer science. The allocation of memory - defining the structure of storage which a program relies upon for its workings - is always fundamentally a different thing from assignment into that storage. The fact that some languages do both things in a one-liner, doesn't mean they become the same things.  
> **username_9** (2023-11-20): @Steve: A compiler processing an ordinary assignment must ensure that it is sequenced after any other operation that might modify the variable in question, even if the question of whether a particular action would modify the variable would be intractable.  A compiler processing an initialization would merely need to ensure that the action is sequenced after any  *compiler-generated* action that reserves space for it.  
> **username_6** (2023-11-21): @supercat, indeed, but just because you put handcuffs on the man doesn't mean he only has one arm. The fact that a particular language puts allocation and assignment in a particular fixed relationship, doesn't mean the distinction between those two things in general discourse has disappeared. The OP asked for the distinction between constants and immutable variables, in no particular language, and the answer is to be found in the difference in how (and when) they are allocated and assigned. (1/2)  
> **username_6** (2023-11-21): Also, the word "immutable" is used much more widely than just languages that have immutable variables enforced by the compiler. It may be applied to objects which have a constructor, mutable fields internally for storage, and read-only properties. The meaning is the same: it means the ability to set the variables once, but not again. It's an extremely common concept. In hardware it's called PROM - constants would be ROM. In databases it's called "insert-only". It's not some fancy new thing that some modern language designer only just invented - it appears frequently in many domains. (2/2)  
> **username_9** (2023-11-21): @Steve: My point is that a compiler that wants to perform the computations that initialize an object's value eagerly, e.g. because the initialization as written would occur in a loop, may perform the initialization as early as it wants if it ensures that the reservation of the storage--*which it controls*--occurs at least as early.  If within a loop a program writes something via an `int*` and then to a pre-existing `int`, a compiler could only hoist the write via `int` if it could prove that the write via `int*` didn't affect the same object.  
> **username_6** (2023-11-21): @supercat, surely in a language where declaration can be made separately from assignment, a compiler could still optimise if it happened to find the two operations together in sequence, and was able to determine that there weren't in fact subsequent assignments?  
> **username_9** (2023-11-21): @Steve: If people writing optimizing compilers focus on "low hanging fruit", they could have compiler that sees `int const y = x;, within a loop having previously see `int const x = something;` hoist the initialization/assignment out of the loop without the compiler having to know or care about whether any code takes the address of `x` or `y`.  If x` and `y` were ordinary objects set via ordinary assignment, a compiler would need to check whether their addresses were taken and, if so, scan extensively for any code that might access them via pointers.  A "low-hanging fruit" optimizer...  
> **username_9** (2023-11-21): ...might, given a language where programmers use that form initialization when practical, sensibly be designed to refrain from trying to optimize ordinary assignments rather than perform the more extensive analysis required to do so in a manner that is soundly reliable.  
---
### Answer by username_10 on 2023-11-20. Score: 2
If it is a variable, regardless if immutable or not, you can get the **address** of it when needed (a language must support a concept of the pointer to immutable object for this to work safely). A compile time constant has no address.

An address of the immutable object can be used:

* For easy check if it is the same object.
* For sharing the immutable object.
* When using immutable pointers to "user objects" like tree data nodes.
* When passing variables of various sizes and types as uniform list of addresses.

In C++, constant references can be used to obtain the immutable address of otherwise mutable variable. This allows to track easier where the variable could probably be modified. For instance, some startup code may set the variable, and the most of the program only see a constant reference to it, making sure the variable cannot be modified any further.
> **Comments:**
> **username_11** (2023-11-21): Other examples of immutable objects are the ones provided at a fixed address by CPUs, microcontrollers or other hardware in the system; they can, for instance, contain a serial number or calibration values (e.g. for an internal temperature sensor or voltage reference).  
---
### Answer by username_12 on 2024-06-19. Score: 2
This is an old question with many good answers but in a quick survey of them I think none mention a particularly important difference between constants and readonly variables.
In C#, named constants must semantically be constant, forever. Why is that?  Because the compilation model of C# assumes that constants are constant forever. Let me illustrate how this goes wrong.  Suppose you have two assemblies, Alpha.DLL and Bravo.DLL, where Bravo has a dependency on Alpha.  In the source code for Alpha, you somewhere have
public const string AlphaCopyright = "Alpha Software Copyright 2024";

If Bravo somewhere in it has
Console.WriteLine("Bravo uses Alpha Corp software");
Console.WriteLine(Alpha.Whatever.AlphaCopyright);

then when Bravo is compiled, the compiler copies the constant value into Bravo.DLL. It does NOT generate code that looks up the value in Alpha.
Now suppose some user out there has a copy of Bravo.DLL and Alpha.DLL, but they update their version of Alpha.DLL to a version that has
public const string AlphaCopyright = "Alpha Software Copyright 2024-2025";

then when they run code in Bravo, it still has the original copyright notice from when it was compiled. It does not pick up the new one, even though from reading the source code, it looks like it should be picking up the latest from whatever version of Alpha is installed.
The compiler assumes that anything marked const will never change even in future versions of the source code, and optimizes accordingly, so if a value could possibly change at some point in the future then mark it as readonly, not as constant, or make it a readonly property. Alpha's developers should have declared this as a property, not a const.
> **Comments:**
> **username_7** (2024-06-21): I wonder how much of it is language semantics and how much of it is DLL quirks. Even with C, you could have a header with a given value for a constant, and a DLL which was compiled with a prior value, and thus no longer match. To me, this indicates not a _semantic_ specificity of C, and more a "failure" of toolchain/distribution in not realizing the discrepancy between the two. Similarly, in your scenario, one could argue the failure is that `Bravo.DLL` was not properly updated when `Alpha.DLL` was...  
> **username_7** (2024-06-21): ... For example, what if we shift to speaking about inline methods, rather than constants. If a method of `Alpha` was inlined in `Bravo.DLL`, and thus subsequently does not match that of `Alpha.DLL`, is it a developer issue because an inline method definition should never change? Or a toolchain/distribution issue because `Bravo.DLL` is not matching `Alpha.DLL`? I'd definitely argue that it's the latter.  
> **username_12** (2024-06-27): @MatthieuM.: Though I take your point, the C# compiler *never* inlines code when generating IL; calls are generated as calls. As you correctly note, it would cause versioning problems if code were inlined across assemblies, but the problem is more general than that: **the C# compiler has no basis upon which to decide whether inlining is an optimization or not!** The *jitter* makes that decision because the jitter knows what the performance characteristics of the hardware are.  
---
### Answer by username_13 on 2023-11-21. Score: 2
The different levels of const-ness are vital to lower levels of systems programming. The important distinction in systems programming between a compile time constant and an immutable variable relates to performance, the programmer's intent, and safety in the presence of external effects. Two prominent examples, Rust and C, make this distinction, and in more or less the same way.
Actual compile-time constants (that definitely are)
C has #defines that can effectively be considered direct textual substitution — copy and paste, if you like. Rust's consts are the same, except they're typed. It is useful to consider that Vec::new() is const!
Why is creating a dynamically growable array const though? Because a vec does not allocate when it's created. There are no runtime side effects at this point. The data structure that makes it up can be populated with the platform's equivalent of a null pointer and zero length entirely at compile time. This leads to confusion over this kind of code:
const CONST_VEC: Vec = Vec::new();

pub fn main() {
    CONST_VEC.push("Hello".into());
    CONST_VEC.push("world!".into());
    dbg!(CONST_VEC);
}

The output of this is:
[src/main.rs:7] CONST_VEC = []

Why? Because this code effectively copy-pastes Vec::new() into each place where you see CONST_VEC. That's what a compile time constant is, a straight up substitution of compile-time-computable values. (You get warnings about this. Just to be clear. Rust knows you're doing something silly here.)
The point of this kind of copy-paste constant is simply to reduce repetition and document intent by naming, without compromising on the performance gains of static program parameters. Repetition of literals is bad because each repetition is the site for a potential mis-copy. Make the infallible machine do the copying! Naming is good, because identical literals may have different purposes, and a simple find-and-replace does not know that. Tell the fallible human which number to replace when a requirement changes!
Immutable variables (that might not be)
In a lot of cases, yes, there is no difference. Indeed in C++ a static const that is not also volatile can be treated the same as a #define or Rust const — a copy-paste. (Someone please correct me if I'm wrong, I'm not nearly as familiar with C++.)
But. In both Rust and C, their respective immutable variables can change, even within the lifetimes of the bindings. This is not some quirk or hackery, it is not unsafe, it is by design. The "immutability" is thus about what the programmer intends and declares, not the data itself.
In Rust, a non-mut variable can change due to interior mutability eg. using one of the UnsafeCell-derived types. You might regard this as a technicality or escape hatch, but interior mutability, and more importantly safe interior mutability, is a fundamental part of Rust's goal of combining usefulness and safety. UnsafeCell might expose an unsafe API, but there are plenty of safe interior mutability wrappers in Rust's stdlib eg. RefCell and Mutex.
In C, a const volatile variable is perfectly valid. What does it mean for a variable to be both const ("does not change") and volatile ("can change outside of operations known to the compiler")? One of those mental models must be wrong, and it's the first one. const simply means that the programmer, the human typing the word const, is declaring that they will not need to write code that directly changes it. The C compiler can enforce this. If the variable is not also volatile, the compiler can also make decisions about optimisations (reordering, combining, even total elision). If it is volatile, the compiler can only (but still) enforce the intent declared by the programmer.
Examples of where this commonly applies, in both languages:

hardware exposed as a read-only memory-mapped peripheral eg. a UART receive buffer
data crossing foreign function interface (FFI) boundaries
data shared across thread or process boundaries.


Embedded and OS programming (for example) depend upon:

having practical support from the language to simultaneously...

constrain what the programmer can mutate...
while accounting for the presence of externally driven side effects;


achieving high performance by exploiting knowledge of program parameters

Taking a higher view then, these different levels of const-ness exist because of the intersection of requirements that are especially common in (although not exclusive to) low-level applications.
> **Comments:**
> **username_14** (2023-11-21): What is FFI? [Foreign function interface](https://en.wikipedia.org/wiki/Foreign_function_interface)?  
> **username_13** (2023-11-21): @PeterMortensen Yes! Sorry for the jargon, I should use the full term on first use.  
---
