www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - What is the difference between enum and shared immutable?

reply Jan =?UTF-8?B?SMO2bmln?= <hrominium gmail.com> writes:
Maybe this is a silly question, but I don't understand completely 
the difference between an `enum` and a `shared immutable`.

I could have:

enum x = 1;

or

shared immutable x = 1;

What is the exact difference between those too?

My best guess is, that shared immutable gets initialized during 
the beginning of the programm execution.
Enum has to be "ready" at compile time.
Is this this accessment correct and complete?
Am I missing anything else?

(If correct, then I understand that shared immutable is capable 
of doing some sideeffects during is construction (if the 
constructor does that))
Oct 28 2020
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
next sibling parent reply matheus <matheus gmail.com> writes:
On Wednesday, 28 October 2020 at 22:07:06 UTC, H. S. Teoh wrote:
 ... (This is why it's a bad idea to use enum with an array 
 literal, because every time it's referenced you get a new copy 
 of the array.)
 ...
Could you please give an example (Snippet) about this? Matheus.
Oct 28 2020
next sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Thursday, 29 October 2020 at 00:55:29 UTC, matheus wrote:
 On Wednesday, 28 October 2020 at 22:07:06 UTC, H. S. Teoh wrote:
 ... (This is why it's a bad idea to use enum with an array 
 literal, because every time it's referenced you get a new copy 
 of the array.)
 ...
Could you please give an example (Snippet) about this?
enum int[] arr = [1,2,3]; someFunc(arr); This is identical to someFunc([1,2,3]); Manifest constants have no address. They are effectively aliases for their values.
Oct 28 2020
parent matheus <matheus gmail.com> writes:
On Thursday, 29 October 2020 at 01:26:38 UTC, Mike Parker wrote:
 enum int[] arr = [1,2,3];
 someFunc(arr);

 This is identical to

 someFunc([1,2,3]);

 Manifest constants have no address. They are effectively 
 aliases for their values.
Hi Mike, I really didn't know about this. Thanks for the information, Matheus.
Oct 28 2020
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 10/28/20 5:55 PM, matheus wrote:
 On Wednesday, 28 October 2020 at 22:07:06 UTC, H. S. Teoh wrote:
 ... (This is why it's a bad idea to use enum with an array literal, 
 because every time it's referenced you get a new copy of the array.)
 ...
Could you please give an example (Snippet) about this? Matheus.
An amusing proof: void main() { enum arr = [ 1 ]; assert(arr.ptr != arr.ptr); // Passes :) } Ali
Oct 29 2020
parent Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Thursday, 29 October 2020 at 16:31:41 UTC, Ali Çehreli wrote:
 On 10/28/20 5:55 PM, matheus wrote:
 On Wednesday, 28 October 2020 at 22:07:06 UTC, H. S. Teoh 
 wrote:
 ... (This is why it's a bad idea to use enum with an array 
 literal, because every time it's referenced you get a new 
 copy of the array.)
 ...
Could you please give an example (Snippet) about this? Matheus.
An amusing proof: void main() { enum arr = [ 1 ]; assert(arr.ptr != arr.ptr); // Passes :) } Ali
Did you just violate the law of identity 👍
Oct 29 2020
prev sibling next sibling parent reply Jan =?UTF-8?B?SMO2bmln?= <hrominium gmail.com> writes:
On Wednesday, 28 October 2020 at 22:07:06 UTC, H. S. Teoh wrote:
 [...]

 An enum only exists at compile-time, and does not occupy any 
 space. Each time it's referenced, a new instance of the value 
 is created.  (This is why it's a bad idea to use enum with an 
 array literal, because every time it's referenced you get a new 
 copy of the array.)

 A shared immutable is initialized at compile-time, and occupies 
 space in the object file / runtime memory. It's also a single 
 instance, and referencing it causes a load of this instance at 
 runtime.  It's not copied unless it's a by-value type, so an 
 array literal will get stored as an array in the executable, 
 and every time you reference it you get a slice of it instead 
 of a copy.


 T
(thanks to you and Mike btw :) Is there some rule of thumb when to use what? I judge that using enum will slow down the compilation process, but might increase performance. So for a small struct, or array enum is completelty fine. Large arrays should then use immutable, let's say when they are larger than 1kb? Regarding the shared keyword, I am not sure if immutables are shared per default. I thought they are not.
Oct 29 2020
next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 29 October 2020 at 08:13:42 UTC, Jan Hönig wrote:
 Regarding the shared keyword, I am not sure if immutables are 
 shared per default. I thought they are not.
You can test this with is(TYPE1==TYPE2) is(shared(immutable(int))==immutable(int))
Oct 29 2020
parent IGotD- <nise nise.com> writes:
On Thursday, 29 October 2020 at 12:21:19 UTC, Ola Fosheim Grøstad 
wrote:
 You can test this with is(TYPE1==TYPE2)

 is(shared(immutable(int))==immutable(int))
So I got that to true, which means that shared immutable is exactly the same as immutable. Shared is implicit for immutable which makes sense. That means that the documentation https://dlang.org/articles/migrate-to-shared.html#immutable is correct at least this one time.
Oct 29 2020
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 10/28/20 3:07 PM, H. S. Teoh wrote:

 A shared immutable is initialized at compile-time,
To prevent a misunderstanding, immutable can be initialized at run time as well. On the other hand, immutable initialized at compile time was surprising to me when I learned it recently: import std; immutable string p; shared static this() { p = environment["PATH"]; // <-- Run time } // Ali learned this relatively recently // (immutable at compile time): immutable lines = import("myfile.txt").splitter('\n').array; pragma(msg, lines); void main() { } Ali
Oct 29 2020
next sibling parent reply IGotD- <nise nise.com> writes:
On Thursday, 29 October 2020 at 16:45:51 UTC, Ali Çehreli wrote:
 import std;

 immutable string p;

 shared static this() {
   p = environment["PATH"];  // <-- Run time
 }
Just to clarify, immutable is allowed to be initialized in ctors but not anything later than that? Moving p = environment["PATH"] to main would generate an error.
Oct 29 2020
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Oct 29, 2020 at 04:56:46PM +0000, IGotD- via Digitalmars-d-learn wrote:
 On Thursday, 29 October 2020 at 16:45:51 UTC, Ali ehreli wrote:
 
 import std;
 
 immutable string p;
 
 shared static this() {
   p = environment["PATH"];  // <-- Run time
 }
 
Just to clarify, immutable is allowed to be initialized in ctors but not anything later than that? Moving p = environment["PATH"] to main would generate an error.
1) Module-level immutable can be initialized either as part of the declaration: immutable int x = 1; 2) Or from inside a shared static this(): immutable int x; shared static this() { x = 2; } Note that initialization from ctor must be done from `shared static this()`, which is global; initialization from `static this` is currently accepted but deprecated, because that's a TLS ctor, and immutables are implicitly shared so you could potentially break immutability by having the TLS ctor set it to a different value per thread. Eventually this will become a hard error. The following are errors: 3) immutable int x = 1; shared static this() { x = 2; // NG: cannot modify immutable } 4) immutable int x; void main() { x = 3; // NG: cannot modify immutable } T -- Lottery: tax on the stupid. -- Slashdotter
Oct 29 2020
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 10/29/20 10:16 AM, H. S. Teoh wrote:

 Module-level immutable can be initialized either as part of the
 declaration:

 	immutable int x = 1;
To add, the expression can be a call to a function that need not return immutable, as long as it is pure, which can be inferred by the compiler for templates. Phew! :) pure char[] makeMutableString() { return "hello".dup; } // This works because makeMutableString() is 'pure', i.e. 'i' cannot // share mutable data. immutable i = makeMutableString(); void main() { } So, instead of adding 'pure' to makeMutableString() like above, one can add another set of parethesis to make it a template. (Two characters instead of four! Win! :p) char[] makeMutableString()() { return "hello".dup; } Ali
Oct 29 2020
prev sibling parent Max Samukha <maxsamukha gmail.com> writes:
On Thursday, 29 October 2020 at 16:45:51 UTC, Ali Çehreli wrote:

 immutable string p;

 shared static this() {
   p = environment["PATH"];  // <-- Run time
 }
Immutable static variables being implicitly non-thread-local is a design mistake. Thread-local immutable variables have the same right to exist as immutable class/struct instance fields. This should be possible without hacks: immutable int val; // thread-specific value static this() { val = ...; } ...because it is logically the same as: struct V { immutable int val; } V val; static this() { val = V(...); }
Oct 30 2020
prev sibling parent reply IGotD- <nise nise.com> writes:
On Wednesday, 28 October 2020 at 21:54:19 UTC, Jan Hönig wrote:
 shared immutable x = 1;
Is there a point to add shared to an immutable? Aren't immutable implicitly also shared?
Oct 28 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 10/28/20 6:28 PM, IGotD- wrote:
 On Wednesday, 28 October 2020 at 21:54:19 UTC, Jan Hönig wrote:
 shared immutable x = 1;
Is there a point to add shared to an immutable? Aren't immutable implicitly also shared?
You are correct: pragma(msg, typeof(x)); // immutable(int) D frequently allows no-op attributes. -Steve
Oct 29 2020
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Oct 29, 2020 at 09:50:28AM -0400, Steven Schveighoffer via
Digitalmars-d-learn wrote:
[...]
 D frequently allows no-op attributes.
[...] I find that to be a bad smell in terms of language design, actually. Either something should be allowed and have a definite effect, or it should not be allowed. Not this murky grey area where you can write something and it seems to be allowed, but doesn't actually have any effect. T -- One reason that few people are aware there are programs running the internet is that they never crash in any significant way: the free software underlying the internet is reliable to the point of invisibility. -- Glyn Moody, from the article "Giving it all away"
Oct 29 2020
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 10/29/20 10:39 AM, H. S. Teoh wrote:
 On Thu, Oct 29, 2020 at 09:50:28AM -0400, Steven Schveighoffer via
Digitalmars-d-learn wrote:
 [...]
 D frequently allows no-op attributes.
[...] I find that to be a bad smell in terms of language design, actually. Either something should be allowed and have a definite effect, or it should not be allowed. Not this murky grey area where you can write something and it seems to be allowed, but doesn't actually have any effect.
I think it's to aid in things like: safe: // lots of things, but only functions are tagged as safe -Steve
Oct 29 2020
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Oct 29, 2020 at 11:00:42AM -0400, Steven Schveighoffer via
Digitalmars-d-learn wrote:
 On 10/29/20 10:39 AM, H. S. Teoh wrote:
 On Thu, Oct 29, 2020 at 09:50:28AM -0400, Steven Schveighoffer via
Digitalmars-d-learn wrote:
 [...]
 D frequently allows no-op attributes.
[...] I find that to be a bad smell in terms of language design, actually. Either something should be allowed and have a definite effect, or it should not be allowed. Not this murky grey area where you can write something and it seems to be allowed, but doesn't actually have any effect.
I think it's to aid in things like: safe: // lots of things, but only functions are tagged as safe
[...] But why can't that be treated differently from explicitly writing safe on a declaration? I mean, yeah, it's easier to implement the compiler that way, but ease of implementation shouldn't count against proper language design! T -- Doubt is a self-fulfilling prophecy.
Oct 29 2020
prev sibling parent Daniel Kozak <kozzi11 gmail.com> writes:
On Thu, Oct 29, 2020 at 4:13 PM H. S. Teoh via Digitalmars-d-learn <
digitalmars-d-learn puremagic.com> wrote:

 But why can't that be treated differently from explicitly writing  safe
 on a declaration?  I mean, yeah, it's easier to implement the compiler
 that way, but ease of implementation shouldn't count against proper
 language design!


 T

 --
 Doubt is a self-fulfilling prophecy.
But what about this: shared { some_ type some_var; immutable int x = 1; } There are many ways to define it and last time when I was looking at how this is implemented in D frontend it was implemented as a bitmask variable and you have no context from where it comes. So only way would be to disallow this within lexer which I do not see as a good options
Oct 30 2020
prev sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Thursday, 29 October 2020 at 14:39:31 UTC, H. S. Teoh wrote:
 On Thu, Oct 29, 2020 at 09:50:28AM -0400, Steven Schveighoffer 
 via Digitalmars-d-learn wrote: [...]
 D frequently allows no-op attributes.
[...] I find that to be a bad smell in terms of language design, actually. Either something should be allowed and have a definite effect, or it should not be allowed. Not this murky grey area where you can write something and it seems to be allowed, but doesn't actually have any effect.
Yes, but that is a tough call. Do you want to catch unintended programmer errors or do you want to make it as easy as possible to write generic code? I'm in favour of max strictness, but then you need to keep the feature set down and make sure it is uniform and orthogonal. But I think it is a bit sad that "shared" isn't enforced so that it could lead to actual benefits. Like requiring that globals are typed shared and enable thread local garbage collection. E.g. GC allocation of non-shared should be on a thread local heap and anything shared should be on a global heap.
Oct 29 2020