digitalmars.D - More Intuitive Syntax for Manifest (enum) Constants
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (15/15) Nov 21 As D already has the keyword `macro` reserved, it just struck me
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (5/9) Nov 21 Should be
- Peter C (18/28) Nov 22 If you want something that is intuitive and instantly
- Per =?UTF-8?B?Tm9yZGzDtnc=?= (8/9) Nov 21 I got this idea when noticing that
- Kapendev (2/17) Nov 21 I would say `macro` is also a bit weird, but I get the idea.
- Stefan Koch (2/9) Nov 21 they look the same to me.
- Paul Backus (5/15) Nov 21 I don't think `macro` is any more intuitive than `enum` here.
- Paul Backus (12/21) Nov 21 By the way, we do not necessarily have to use a keyword for this.
- Walter Bright (3/3) Nov 21 ```d
- Peter C (15/18) Nov 21 I've never ever liked this misuse of enum in D to basically
- Paul Backus (7/14) Nov 21 This is actually mostly inherited from C.
- Peter C (18/33) Nov 22 In my opinion, there is far too much overloading of keywords in
- Walter Bright (5/6) Nov 22 ```d
- Kapendev (16/19) Nov 22 I think this isn't very clear and can confuse people. For better
- Walter Bright (11/11) Nov 22 Allow me to point out `static` in C and C++! and its many porpoises!! D ...
- Peter C (29/33) Nov 22 Actually, outside of OO like programming, 'final' does seem like
- Walter Bright (15/19) Nov 22 Long ago, I tried my hand at writing a user interface library. I was sho...
- Kagamin (6/10) Nov 24 Most manifest constants are indeed enums. The poster you reply to
- Walter Bright (2/6) Nov 24 Yes, making them strongly typed is more of a nuisance than a benefit.
- Peter C (15/17) Nov 24 "Outlandish reasoning" -> a line of thinking or an explanation
- Peter C (7/10) Nov 24 The claim is partially true but overstated and misleading.
- Peter C (13/16) Nov 24 For those listening, please don't follow that advice.
- Jonathan M Davis (22/24) Nov 25 Also, the enumerated values in an enum type are effectively manifest
- Dejan Lekic (13/23) Nov 25 I thought I would skip this discussion, but I could not resist to
- Zealot (2/16) Nov 25 alias? :D
- user1234 (11/30) Nov 25 Styx uses `alias` for the equivalent of D manifest constants.
- Peter C (20/32) Nov 25 After exploring D's enum further, I tend to agree.
- monkyyy (3/6) Nov 25 Ctfe and pure are *NOT* quite the same thing, the compiler only
- Peter C (11/12) Nov 22 While not advocating for a change here, if I wanted to signal to
As D already has the keyword `macro` reserved, it just struck me that I personally think ```d macro N = 42; ``` is more intuitive and recognizable than ```d macro N = 42; ``` . Especially for new developers. This makes it more obvious that D's manifest constants is instantly inlined by the compiler opposite to how `static immutable N = 42;` is treated. What do you think?
Nov 21
On Friday, 21 November 2025 at 11:20:08 UTC, Per Nordlöw wrote:is more intuitive and recognizable than ```d macro N = 42; ```Should be ```d enum N = 42; ```
Nov 21
On Friday, 21 November 2025 at 11:20:51 UTC, Per Nordlöw wrote:On Friday, 21 November 2025 at 11:20:08 UTC, Per Nordlöw wrote:If you want something that is intuitive and instantly recognizable (i.e. no keyword overloading): constexpr int N = 42; // guaranteed to have no runtime memory allocation; // its value is folded into the executable code. of course, then you have a new keyword requirement for D, which will likely go nowhere.... as for.. macro N = 42; ... well... yuk! I presume enum N = 42; already guarantees the above anyway, so I wouldn't be arguing for a change here. But if designing a language from scratch, I would certainly not be considering overloading enum for this purpose (nor would I be considering using 'macro'!) As it is, the syntax for expressing a manifest (enum) constant in D already exists, and it won't likely change. The conflict is semantic, not technical.is more intuitive and recognizable than ```d macro N = 42; ```Should be ```d enum N = 42; ```
Nov 22
On Friday, 21 November 2025 at 11:20:08 UTC, Per Nordlöw wrote:What do you think?I got this idea when noticing that https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#semanticTokenTypes has no entry named `constant` and it's meaning of `enum` is always a enumeration type. The symbol `SemanticTokenTypes.enumMember` could be reused in this case but I believe `SemanticTokenTypes.macro` better resembles the semantics of D's manifest constants.
Nov 21
On Friday, 21 November 2025 at 11:20:08 UTC, Per Nordlöw wrote:As D already has the keyword `macro` reserved, it just struck me that I personally think ```d macro N = 42; ``` is more intuitive and recognizable than ```d macro N = 42; ``` . Especially for new developers. This makes it more obvious that D's manifest constants is instantly inlined by the compiler opposite to how `static immutable N = 42;` is treated. What do you think?I would say `macro` is also a bit weird, but I get the idea.
Nov 21
On Friday, 21 November 2025 at 11:20:08 UTC, Per Nordlöw wrote:```d macro N = 42; ``` is more intuitive and recognizable than ```d macro N = 42; ```they look the same to me.
Nov 21
On Friday, 21 November 2025 at 11:20:08 UTC, Per Nordlöw wrote:As D already has the keyword `macro` reserved, it just struck me that I personally think ```d macro N = 42; ``` is more intuitive and recognizable than ```d enum N = 42; ``` . Especially for new developers.I don't think `macro` is any more intuitive than `enum` here. Most "new developers" don't know C or C++, and will not have any reason to associate the word "macro" with the concept of "a compile-time constant."
Nov 21
On Friday, 21 November 2025 at 11:20:08 UTC, Per Nordlöw wrote:As D already has the keyword `macro` reserved, it just struck me that I personally think ```d macro N = 42; ``` is more intuitive and recognizable than ```d enum N = 42; ```By the way, we do not necessarily have to use a keyword for this. The D grammar allows declarations with only a UDA to the left of the variable name, rather than a type or storage class: ```d UDA N = 42; ``` So if we created a new `core.attribute` UDA, we could potentially write code like this: ```d manifestConstant N = 42; ```
Nov 21
On Saturday, 22 November 2025 at 01:48:43 UTC, Walter Bright wrote:```d enum N = 42; ```I've never ever liked this misuse of enum in D to basically reflect a lightweight constant. This is what happens when you repurpose a keyword to define a named constant, instead of a strict collection of values, which is what an enum is meant to be. You seem intent on doing the same with 'final', it seems - i.e. repurposing it to mean single assignment. To me, it represents a lack of clarity in language design (i.e. to benefit the compiler??, but at the cost of semantic integrity). In C it's -> #define N = 42 In D, it should have been -> const int N = 42; not -> enum N = 42; // to me, this misrepresents the purpose of an enum
Nov 21
On Saturday, 22 November 2025 at 02:30:12 UTC, Peter C wrote:On Saturday, 22 November 2025 at 01:48:43 UTC, Walter Bright wrote:This is actually mostly inherited from C. In C, you can write code like this to define a compile-time constant: enum { N = 42 }; The only difference in D is that you are allowed to leave out the curly braces.```d enum N = 42; ```I've never ever liked this misuse of enum in D to basically reflect a lightweight constant.
Nov 21
On Saturday, 22 November 2025 at 05:05:31 UTC, Paul Backus wrote:On Saturday, 22 November 2025 at 02:30:12 UTC, Peter C wrote:In my opinion, there is far too much overloading of keywords in programming languages (both within, and across). It's always creating mental dissonance. When I see [enum N = 42;] it immediately creates mental dissonance (perhaps because I don't see it often enough, thankfully). With this, I have to pause for a moment to remember that it's actually attempting to define a constant named N without defining the containing enum type. I guess because of D's close ties to C, the C 'enum trick' makes sense to have in D also. But even so.... immediate unambiguous clarity. I do not have to pause and make sense of this. It's a constant integer expression. type definition, for a set of related members. I guess I can live with enum N = 42; .. but still....On Saturday, 22 November 2025 at 01:48:43 UTC, Walter Bright wrote:This is actually mostly inherited from C. In C, you can write code like this to define a compile-time constant: enum { N = 42 }; The only difference in D is that you are allowed to leave out the curly braces.```d enum N = 42; ```I've never ever liked this misuse of enum in D to basically reflect a lightweight constant.
Nov 22
On 11/22/2025 12:10 AM, Peter C wrote:```d enum N = 42; ``` is so much simpler, for the win! Especially when you write a bunch of them.
Nov 22
On Saturday, 22 November 2025 at 08:10:44 UTC, Peter C wrote:immediate unambiguous clarity. I do not have to pause and make sense of this. It's a constant integer expression.I think this isn't very clear and can confuse people. For better readability, you should actually use something more in line with modern language design, like: public static class FOO { public const int Value = 42; } ``` This gives the constant a proper semantic boundary and lets you extend it later if needed. Raw enums like `enum FOO = 42;`, or even the more primitive and worse looking `public const int N = 42`, just don't scale in production code.
Nov 22
On Saturday, 22 November 2025 at 09:39:03 UTC, Kapendev wrote:
I think this isn't very clear and can confuse people. For
better readability,
you should actually use something more in line with modern
language design, like:
public static class FOO
{
public const int Value = 42;
}
```
This gives the constant a proper semantic boundary and lets you
extend it later
thats still bad style
public static class FOO
{
private const int Value = 42;
///gets the value
public const ref int getValue() property
{
assert(&Value is not null);
return Value;
}
}
```
Nov 23
On Sunday, 23 November 2025 at 21:19:05 UTC, monkyyy wrote:On Saturday, 22 November 2025 at 09:39:03 UTC, Kapendev wrote:Overall, better, but you forgot to put ` trusted` there. Return `ref` is unsafe, but your code looks correct, so it's okay. It would be nicer if you wrapped that getter in a safer abstraction.I think this isn't very clear and can confuse people. For better readability, you should actually use something more in line with modern language design, like: public static class FOO { public const int Value = 42; } ``` This gives the constant a proper semantic boundary and lets you extend it laterthats still bad style public static class FOO { private const int Value = 42; ///gets the value public const ref int getValue() property { assert(&Value is not null); return Value; } } ```
Nov 23
On Sunday, 23 November 2025 at 22:16:41 UTC, Kapendev wrote:On Sunday, 23 November 2025 at 21:19:05 UTC, monkyyy wrote:const ref is acceptable according to uncle bob during his 3 bookOn Saturday, 22 November 2025 at 09:39:03 UTC, Kapendev wrote:Overall, better, but you forgot to put ` trusted` there. Return `ref` is unsafe, but your code looks correct, so it's okay. It would be nicer if you wrapped that getter in a safer abstraction.[...]thats still bad style public static class FOO { private const int Value = 42; ///gets the value public const ref int getValue() property { assert(&Value is not null); return Value; } } ```
Nov 23
Allow me to point out `static` in C and C++! and its many porpoises!! D takes
some of that, too. But at least D has `private` instead of `static`.
I agree `enum` for this seems a bit awkward at first, but it smooths out
naturally pretty quickly. After all, just think of it as an "enumerated
constant" with only one value, so why bother with the { }.
An enum manifest constant has some subtle differences with `const`:
1. it does not allocate storage
2. it cannot be a pointer
As for `final`, it seems the perfect keyword for it. What semantic integrity is
it losing? Currently, applying `final` to a variable declaration gives an error.
I have difficulty seeing `macro` being better.
Nov 22
On Saturday, 22 November 2025 at 08:59:59 UTC, Walter Bright wrote:... As for `final`, it seems the perfect keyword for it. What semantic integrity is it losing? Currently, applying `final` to a variable declaration gives an error.Actually, outside of OO like programming, 'final' does seem like the perfect fit - because you typically won't ever see that word used (expect for 'final switch') It's when it appears in the context of other finals, that it creates mental dissonance: final class Base { final void printInfo() {} final Base finalFieldRef; } Of course, putting final on the methods here is a bit redundant, since the class is final anyway, but this pattern is still used. So, yes, final is an 'intuitive' syntax choice for SAA - but only when used outside of code above. Most likely, for immediate clarity (for myself and others), I'd have to include a comment: final class Base { final void printInfo() {} final Base finalFieldRef; // enforcing a single assignment here } This is a bit off topic of course, but I can easily twist this same argument around for why there should have been a more intuitive syntax for mainfest constants, instead of overloading enum to also mean a non-type definition - i.e. the tool for defining a type should not be the tool for defining a value.
Nov 22
On 11/22/2025 1:32 AM, Peter C wrote:This is a bit off topic of course, but I can easily twist this same argument around for why there should have been a more intuitive syntax for mainfest constants, instead of overloading enum to also mean a non-type definition - i.e. the tool for defining a type should not be the tool for defining a value.Long ago, I tried my hand at writing a user interface library. I was shocked to discover that what was consistent for a computer was very inconsistent to a user, and vice versa. (Did you know that the ancient Greek Parthenon does not use straight lines, but they look straight? How did the Greeks figure that out?) D isn't consistent with what would work best for a computer, either, which is why it is converted to "intermediate code" by the front end. There are a lot of inconsistencies, but they work for humans. `final` is currently used for statements, classes, and derived functions. Adding them for declarations is not confusing for a human, and keeping the number of keywords low is good. I understand you disagree, and that's ok. That's why designing a programming language is more of an art than a science. The `enum E = 24;` syntax looked a bit odd at first, but seems perfectly natural to me now.
Nov 22
On Sunday, 23 November 2025 at 07:15:27 UTC, Walter Bright wrote:D isn't consistent with what would work best for a computer, either, which is why it is converted to "intermediate code" by the front end. There are a lot of inconsistencies, but they work for humans.Most manifest constants are indeed enums. The poster you reply to typed, which greatly hurts interoperability, as a result interoperable enums are better declared as integer or string constants.
Nov 24
On 11/24/2025 7:46 AM, Kagamin wrote:Most manifest constants are indeed enums. The poster you reply to is known to interoperability, as a result interoperable enums are better declared as integer or string constants.Yes, making them strongly typed is more of a nuisance than a benefit.
Nov 24
On Monday, 24 November 2025 at 15:46:28 UTC, Kagamin wrote:... the poster you reply to is known to have outlandish reasoning."Outlandish reasoning" -> a line of thinking or an explanation that is extremely strange, unusual, bizarre, or improbable. Mmm. You really think my reasoning is that? You may well disagree with: const int SIZE = 5; But there is nothing outlandish about that, surely. It's effectively a C++ constexpr. Sure, in C++, you could also do: enum { SIZE = 5 }; But constexpr is best practice I believe. Again, I'm not arguing for a change here (i.e if you use [ enum SZ = 10; ] often enough, you'll quickly adapt to accepting it), but I have to push back on your claim that my preference to not use [ enum SZ = 10; ] is somehow based on outlandish reasoning. That just sounds like a slur to me.
Nov 24
On Monday, 24 November 2025 at 15:46:28 UTC, Kagamin wrote:interoperability, as a result interoperable enums are better declared as integer or string constants.The claim is partially true but overstated and misleading. 1. The "Strongly Typed" Part (True) 2. The "Hurts Interoperability" Part (Overstated) 3. The Conclusion (Misleading) type are the standard, recommended solution.
Nov 24
On Monday, 24 November 2025 at 15:46:28 UTC, Kagamin wrote:... interoperable enums are better declared as integer or string constants.For those listening, please don't follow that advice. Best practice, is that you should always consider explicitly definition. Here's what happens when you don't follow best practice: public enum BadNativeResult { SUCCESS = 0, MAX_ERROR = 0xFFFFFFFF // what do you think will happen here? } [DllImport("NativeLib.dll")] public static extern BadNativeResult GetLastError();
Nov 24
On Monday, 24 November 2025 at 23:07:25 UTC, Peter C wrote:On Monday, 24 November 2025 at 15:46:28 UTC, Kagamin wrote:Not sure, but if you really care then just add a type to the enum.... interoperable enums are better declared as integer or string constants.For those listening, please don't follow that advice. Best practice, is that you should always consider explicitly definition. Here's what happens when you don't follow best practice: public enum BadNativeResult { SUCCESS = 0, MAX_ERROR = 0xFFFFFFFF // what do you think will happen here? } [DllImport("NativeLib.dll")] public static extern BadNativeResult GetLastError();standard robust safe recommended solutionSource?????
Nov 24
On Tuesday, 25 November 2025 at 01:58:54 UTC, Kapendev wrote:Not sure, but if you really care then just add a type to the enum.In D, I wasn't aware you could do that for 'a single' manifest constant: enum N = 42; // this is how I've seen it used (in the opening post). I had just assumed that form doesn't support a type annotation. enum double A = 0.2; // turns out, you CAN actually type it. Nice! so I'm a little less troubled by it now ;-)me! from experience.standard robust safe recommended solutionSource?????
Nov 25
On Tuesday, 25 November 2025 at 09:56:48 UTC, Peter C wrote:In D, I wasn't aware you could do that for 'a single' manifest constant:Am I understood it right, that you made some suggestions regarding language changes without knowing the language itself?
Nov 25
On Tuesday, 25 November 2025 at 10:10:35 UTC, Serg Gini wrote:On Tuesday, 25 November 2025 at 09:56:48 UTC, Peter C wrote:I did not open this conversation. And if you read my posts correctly, I was very explicit about *not* advocating for a change. I was just putting forth my reasoning as to why I thought, that the tool for defining a type should not be the tool for defining a value. public const double VAL = 0.2; I find that semantically more cleaner than using an enum type. That is really all I'm saying. Agree or disagree.. I couldn't give a flying %$ff ;-)In D, I wasn't aware you could do that for 'a single' manifest constant:Am I understood it right, that you made some suggestions regarding language changes without knowing the language itself?
Nov 25
On Monday, 24 November 2025 at 23:07:25 UTC, Peter C wrote:On Monday, 24 November 2025 at 15:46:28 UTC, Kagamin wrote:After you said that constants should be declared as `const int` because enums are weird :)... interoperable enums are better declared as integer or string constants.For those listening, please don't follow that advice.Best practice, is that you should always consider explicitly definition. Here's what happens when you don't follow best practice: public enum BadNativeResult { SUCCESS = 0, MAX_ERROR = 0xFFFFFFFF // what do you think will happen here? }The alternative is to not create a problem from the start.
Nov 25
On Sunday, November 23, 2025 12:15:27 AM Mountain Standard Time Walter Bright via Digitalmars-d wrote:The `enum E = 24;` syntax looked a bit odd at first, but seems perfectly natural to me now.Also, the enumerated values in an enum type are effectively manifest constants. So, while using enum for manifest constants might seem odd a first, it's actually quite logically consistent. IMHO, in practice, this is a total non-issue. It's confusing for some folks who are new to the language, but they typically get over it pretty quickly. That leaves the folks who dislike it based on the principle that enum is short for enumeration, and there's only one value, not an enumerated set of values, but I think that the folks who stay hung up on that are in the minority. Some folks who don't complain about it probably would still pick a different keyword if they had the choice, but it just isn't a big enough deal for most folks to complain about it once they get used to it. And honestly, if I were to create a new version of D with all of the various changes that I think would ideally be changed if we didn't care about backwards compatibility, I'd probably just leave manifest constants the way that they are. It simply isn't worth adding a keyword for this concept, and it has the benefit that both enum values and manifest constants which are designated via enum behave the same way. So, arguably, using a different keyword would just fix one perceieved inconsistency by adding a new name for what is practically speaking the same thing but in a slightly different form. - Jonathan M Davis
Nov 25
On Tuesday, 25 November 2025 at 10:54:06 UTC, Jonathan M Davis wrote:And honestly, if I were to create a new version of D with all of the various changes that I think would ideally be changed if we didn't care about backwards compatibility, I'd probably just leave manifest constants the way that they are. It simply isn't worth adding a keyword for this concept, and it has the benefit that both enum values and manifest constants which are designated via enum behave the same way. So, arguably, using a different keyword would just fix one perceieved inconsistency by adding a new name for what is practically speaking the same thing but in a slightly different form.I thought I would skip this discussion, but I could not resist to write my suggestion here. We discussed `final int E = 42`, `manifest E = 42`, and few other options on but I do not remember that we discussed this: ```d named E = 42; named APP_VERSION = "1.0.0"; ``` This comes from the fact that manifest constants are "named", "literal", "symbolic" constants. A good alternative in my opinion would be `symbol E = 42;`
Nov 25
On Tuesday, 25 November 2025 at 12:20:13 UTC, Dejan Lekic wrote:On Tuesday, 25 November 2025 at 10:54:06 UTC, Jonathan M Davis wrote:alias? :D[...]I thought I would skip this discussion, but I could not resist to write my suggestion here. We discussed `final int E = 42`, `manifest E = 42`, and few other options on but I do not remember that we discussed this: ```d named E = 42; named APP_VERSION = "1.0.0"; ``` This comes from the fact that manifest constants are "named", "literal", "symbolic" constants. A good alternative in my opinion would be `symbol E = 42;`
Nov 25
On Tuesday, 25 November 2025 at 15:26:06 UTC, Zealot wrote:On Tuesday, 25 November 2025 at 12:20:13 UTC, Dejan Lekic wrote:Styx uses `alias` for the equivalent of D manifest constants. That works because the language also has [expression aliases](https://styx-lang.gitlab.io/styx/expression_alias.html) ``` // polymorphic version alias e0 => 0; // monomorphic version (evaluated once in situe) const alias e0 => 0; ``` anyway, I dont think this is a good idea for D.On Tuesday, 25 November 2025 at 10:54:06 UTC, Jonathan M Davis wrote:alias? :D[...]I thought I would skip this discussion, but I could not resist to write my suggestion here. We discussed `final int E = 42`, `manifest E = 42`, and few other options on but I do not remember that we discussed this: ```d named E = 42; named APP_VERSION = "1.0.0"; ``` This comes from the fact that manifest constants are "named", "literal", "symbolic" constants. A good alternative in my opinion would be `symbol E = 42;`
Nov 25
On Tuesday, 25 November 2025 at 10:54:06 UTC, Jonathan M Davis wrote:... And honestly, if I were to create a new version of D with all of the various changes that I think would ideally be changed if we didn't care about backwards compatibility, I'd probably just leave manifest constants the way that they are. It simply isn't worth adding a keyword for this concept, and it has the benefit that both enum values and manifest constants which are designated via enum behave the same way. So, arguably, using a different keyword would just fix one perceieved inconsistency by adding a new name for what is practically speaking the same thing but in a slightly different form. - Jonathan M DavisAfter exploring D's enum further, I tend to agree. I like (and just discovered) that D's enum can be initialized by a CTFE-compatible function (pure). forcing you to switch from const to static readonly for initialization via a function. So at least D's use of enum provides a consistent entry point for manifest constants - even in Rust you would have to switch from const to const fn. Walter said (in previous post here): "The `enum E = 24;` syntax looked a bit odd at first, but seems perfectly natural to me now.". So really, I just had the same reaction. But I'm getting more comfortable with it, as begin to understand its role in D a little better (particulary in combination with CTFE). But to clear [yet again] I was never advocating for a change to D - I was just expressing an opinion.
Nov 25
On Tuesday, 25 November 2025 at 23:55:08 UTC, Peter C wrote:I like (and just discovered) that D's enum can be initialized by a CTFE-compatible function (pure).Ctfe and pure are *NOT* quite the same thing, the compiler only pays attention to ctfe compatibility :D
Nov 25
On Friday, 21 November 2025 at 11:20:08 UTC, Per Nordlöw wrote:..While not advocating for a change here, if I wanted to signal to the compiler that I wanted a compile-time constant expression, but I didn't like using enum to express that intent, then maybe: const int SIZE = 5; // effectively the same as C++ -> constexpr int N = 5; This preserves 'const' for runtime use. Again, I'm *not* advocating for a change, but if I could choose between using const or enum, I'd almost certainly always choose const, as it seems more semantically cleaner to me - assuming you know what the infers ;-)
Nov 22









Peter C <peterc gmail.com> 