digitalmars.D - enum str = "abc"; vs string str = "abc";
- Victor Porton (9/9) Jan 16 2019 What is more space efficient:
- H. S. Teoh (19/33) Jan 16 2019 Strings are a bit special, in that the compiler automatically stores
- Victor Porton (3/11) Jan 16 2019 I haven't got what is your argument pro `immutable str` and so
- Johannes Loher (14/17) Jan 16 2019 They are, if they are declared immutable (which is no problem if
- Johannes Loher (22/39) Jan 16 2019 Actually in this case, it can also simply be `immutable i = 0;`,
- Steven Schveighoffer (13/16) Jan 16 2019 Not sure what you mean, this should work.
- H. S. Teoh (5/14) Jan 16 2019 Ahh, I see. I stand corrected. :-)
- Walter Bright (14/23) Jan 16 2019 You can find this out by:
- Mathias Lang (36/45) Jan 16 2019 I've seen people using mostly `enum` over `(static) immutable`,
- Walter Bright (2/2) Jan 16 2019 That's true for arrays, but for strings the compiler will emit only one ...
- Meta (6/8) Jan 17 2019 While we have your ear, Walter, what about an enum that is an
- H. S. Teoh (8/16) Jan 17 2019 You could just check the disassembly yourself. On my system, I found
- Walter Bright (4/5) Jan 17 2019 It's a good practice to follow. I don't always remember what it does exa...
What is more space efficient: enum str = "safjkdfjksdlfkdsj"; or string str = "safjkdfjksdlfkdsj"; ? with the first code fragment, won't the string be re-created and re-inserted into the object file one time whenever str is used, rather than once? What of the two you would recommend?
Jan 16 2019
On Wed, Jan 16, 2019 at 06:21:29PM +0000, Victor Porton via Digitalmars-d wrote:What is more space efficient: enum str = "safjkdfjksdlfkdsj"; or string str = "safjkdfjksdlfkdsj"; ? with the first code fragment, won't the string be re-created and re-inserted into the object file one time whenever str is used, rather than once?Strings are a bit special, in that the compiler automatically stores them in a string table and emits them only once. However, you're quite right that using enum with arrays in general is not a good idea space-wise.What of the two you would recommend?Use: immutable str = "..."; in module-global scope. Or if this is inside a function, static immutable str = "..."; This places it in the data section of the object file and elides the extra pointer/size pair of `str` if it were mutable. OTOH, if `str` is only referenced at compile-time, then it's more efficient to use the enum, because then it won't even appear in the object file. :-) Also, you may have no choice but to use an enum if `str` is referenced by compile-time code, since static globals would not be readable at compile-time. T -- Study gravitation, it's a field with a lot of potential.
Jan 16 2019
On Wednesday, 16 January 2019 at 18:50:51 UTC, H. S. Teoh wrote:On Wed, Jan 16, 2019 at 06:21:29PM +0000, Victor Porton viaI haven't got what is your argument pro `immutable str` and so against enum.What of the two you would recommend?Use: immutable str = "..."; in module-global scope. Or if this is inside a function, static immutable str = "..."; This places it in the data section of the object file and elides the extra pointer/size pair of `str` if it were mutable.
Jan 16 2019
On Wednesday, 16 January 2019 at 18:50:51 UTC, H. S. Teoh wrote:Also, you may have no choice but to use an enum if `str` is referenced by compile-time code, since static globals would not be readable at compile-time.They are, if they are declared immutable (which is no problem if using enum would also be ok). The following program outputs "0" during compilation: ``` static immutable i = 0; static if (i == 0) { pragma(msg, i); } void main() { } ```
Jan 16 2019
On Wednesday, 16 January 2019 at 19:06:18 UTC, Johannes Loher wrote:On Wednesday, 16 January 2019 at 18:50:51 UTC, H. S. Teoh wrote:Actually in this case, it can also simply be `immutable i = 0;`, the `static` keyword doesn't do anything in this case. This also works and also prints "0" during compilation: ``` void main() { static immutable i = 0; static if (i == 0) { pragma(msg, i); } } ``` The argument for using `static immutable` (or `immutable` at module level) is that unlike enum, it will only ever use one instance. It will not allocate several times. As was mentioned before, this is also true for `enum` when used with strings, but strings are a special case. For other array types (and associative array types), a new instance is allocated whenever the `enum` is used.Also, you may have no choice but to use an enum if `str` is referenced by compile-time code, since static globals would not be readable at compile-time.They are, if they are declared immutable (which is no problem if using enum would also be ok). The following program outputs "0" during compilation: ``` static immutable i = 0; static if (i == 0) { pragma(msg, i); } void main() { } ```
Jan 16 2019
On 1/16/19 1:50 PM, H. S. Teoh wrote:Also, you may have no choice but to use an enum if `str` is referenced by compile-time code, since static globals would not be readable at compile-time.Not sure what you mean, this should work. Only immutable globals that aren't initialized until runtime can't be used. e.g.: immutable string s; immutable string s2 = "abc"; shared static this() { s = "abc"; } pragma(msg, s); // error pragma(msg, s2); // OK -Steve
Jan 16 2019
On Wed, Jan 16, 2019 at 02:10:02PM -0500, Steven Schveighoffer via Digitalmars-d wrote:On 1/16/19 1:50 PM, H. S. Teoh wrote:Ahh, I see. I stand corrected. :-) T -- Verbing weirds language. -- Calvin (& Hobbes)Also, you may have no choice but to use an enum if `str` is referenced by compile-time code, since static globals would not be readable at compile-time.Not sure what you mean, this should work. Only immutable globals that aren't initialized until runtime can't be used.
Jan 16 2019
On 1/16/2019 10:21 AM, Victor Porton wrote:What is more space efficient: enum str = "safjkdfjksdlfkdsj"; or string str = "safjkdfjksdlfkdsj"; ?You can find this out by: dmd -c test.d obj2asm test.obj Also, enum s = "hello"; size_t i = s.length; The string "hello" does not appear in the object file. immutable string s = "hello"; size_t i = s.length; The string "hello" does appear in the object file. immutable string s = "hello"; immutable string t = "hello"; The string "hello" appears only once in the object file.
Jan 16 2019
On Wednesday, 16 January 2019 at 18:21:29 UTC, Victor Porton wrote:What is more space efficient: enum str = "safjkdfjksdlfkdsj"; or string str = "safjkdfjksdlfkdsj"; ? with the first code fragment, won't the string be re-created and re-inserted into the object file one time whenever str is used, rather than once? What of the two you would recommend?I've seen people using mostly `enum` over `(static) immutable`, but... When we ported our code from D1 to D2 in Sociomantic, we created a small fixup tool (https://github.com/sociomantic-tsunami/d1to2fix) and one of its job was to convert D1-style manifest constant (`const X = initializer;`) into "D2 style" (`enum X = initializer;`). And allocations started to show up where they would not before. After we got a rather complete and insightful explanation of the difference between `enum` and `static immutable` by Don Clugston, we switched to `static immutable` (almost) everywhere, and that was definitely a win. You can see `enum` as a `#define`. It will get "copy-pasted" everywhere, and thus, it's a rvalue (you can't take the address of an enum). On the other hand, `static immutable` are actual variable that will live in the binary. They are a symbol you can take the address of. They behave exactly like you would want a manifest constant to behave. There is only one corner case I know of where enum is more practical, it's the following code: ```D static immutable INITIALIZER = [1, 2, 3, 4]; // Does not work because it tries to do immutable -> mutable enum INITIALIZER = [1, 2, 3, 4]; // Works because every time it is used, it allocates a new array void foo (int[] value = INITIALIZER) { ... } ``` That being said, the DMD frontend is clever enough to avoid pointless allocations in the most obvious cases. So for example an array literal indexed by a compile-time known index will not allocate (`enum ARR = [0, 1, 2]; int i = ARR[0];`). However, if the index is not known at compile time, it will allocate every time with `enum`, never with `static immutable`. TL;DR: Use `static immutable` by default, `enum` if you want a `#define`.
Jan 16 2019
That's true for arrays, but for strings the compiler will emit only one string, and everything else will refer to that.
Jan 16 2019
On Thursday, 17 January 2019 at 06:00:09 UTC, Walter Bright wrote:That's true for arrays, but for strings the compiler will emit only one string, and everything else will refer to that.While we have your ear, Walter, what about an enum that is an array of strings? Will an enum array of strings with length N behave the same way as a single string and only emit those N strings once, or will a new array be allocated each time the enum is used?
Jan 17 2019
On Thu, Jan 17, 2019 at 03:16:16PM +0000, Meta via Digitalmars-d wrote:On Thursday, 17 January 2019 at 06:00:09 UTC, Walter Bright wrote:You could just check the disassembly yourself. On my system, I found that the strings themselves are only stored once. But the outer array is allocated and repopulated each time, each time by a call to a druntime function _d_arrayliteralTX. T -- Genius may have its limitations, but stupidity is not thus handicapped. -- Elbert HubbardThat's true for arrays, but for strings the compiler will emit only one string, and everything else will refer to that.While we have your ear, Walter, what about an enum that is an array of strings? Will an enum array of strings with length N behave the same way as a single string and only emit those N strings once, or will a new array be allocated each time the enum is used?
Jan 17 2019
On 1/17/2019 7:32 AM, H. S. Teoh wrote:You could just check the disassembly yourself.It's a good practice to follow. I don't always remember what it does exactly, as it changes over time, and multiple people have contributed to it. I check the assembler output myself just to be sure.
Jan 17 2019