Jump to page: 1 2
Thread overview
enum str = "abc"; vs string str = "abc";
Jan 16, 2019
Victor Porton
Jan 16, 2019
H. S. Teoh
Jan 16, 2019
Victor Porton
Jan 16, 2019
Johannes Loher
Jan 16, 2019
Johannes Loher
Jan 16, 2019
H. S. Teoh
Jan 16, 2019
Walter Bright
Jan 17, 2019
Mathias Lang
Jan 17, 2019
Walter Bright
Jan 17, 2019
Meta
Jan 17, 2019
H. S. Teoh
Jan 18, 2019
Walter Bright
January 16, 2019
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?
January 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.
January 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 via
>> 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.

I haven't got what is your argument pro `immutable str` and so against enum.
January 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()
{

}
```

January 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
January 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:
>> 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()
> {
>
> }
> ```

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.
January 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:
> > 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.

Ahh, I see.  I stand corrected. :-)


T

-- 
Verbing weirds language. -- Calvin (& Hobbes)
January 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.
January 17, 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`.
January 16, 2019
That's true for arrays, but for strings the compiler will emit only one string, and everything else will refer to that.
« First   ‹ Prev
1 2