www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Type of string literal concatenated with non-immutable char array

reply Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
Given

     char x[];

why is

     typeof("a" ~ x)

`char[]` when

     typeof("a" ~ x.idup)

is

     `string`?

My case is

class NameLookupException : Exception
{
     this(string name) {
         super("Name " ~ name ~ " could not be found");
     }
     this(scope const(char)[] name) {
         super("Name " ~ name.idup ~ " could not be found");
     }
}

where I instead would like to only need

class NameLookupException : Exception
{
     this(scope const(char)[] name) {
         super("Name " ~ name ~ " could not be found");
     }
}

Why isn't

     "Name " ~ name ~ " could not be found"

implicitly convertible to `string`?

Would

class NameLookupException : Exception
{
     this(scope const(char)[] name)  trusted {
         super("Name " ~ cast(string)name ~ " could not be found");
     }
}

be ok?
Jan 31
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On Sunday, 31 January 2021 at 21:48:09 UTC, Per Nordlöw wrote:
 Given

     char x[];

 why is

     typeof("a" ~ x)

 `char[]` when

     typeof("a" ~ x.idup)

 is

     `string`?

 My case is

 class NameLookupException : Exception
 {
     this(string name) {
         super("Name " ~ name ~ " could not be found");
     }
     this(scope const(char)[] name) {
         super("Name " ~ name.idup ~ " could not be found");
     }
 }

 where I instead would like to only need

 class NameLookupException : Exception
 {
     this(scope const(char)[] name) {
         super("Name " ~ name ~ " could not be found");
     }
 }

 Why isn't

     "Name " ~ name ~ " could not be found"

 implicitly convertible to `string`?
Because if you have arrays of reference types, it's possible to change an element of the mutable array, which will affect the immutable array, those breaking the immutability. Example: class Foo { int a; } void main() { Foo[] a = [new Foo]; immutable(Foo)[] b = [new Foo]; // `string` is an alias for `immutable(char)[]` auto c = b ~ a; a[0].a = 3; assert(c[1].a == 3); } Due to language consistency it should behave the same for all types. In the above example, `c` is typed as `const(Foo)[]`. Although, I wonder why in your example the concatenation is typed as `char[]` instead of `const(char)[]`. Perhaps that's a bug. -- /Jacob Carlborg
Feb 01
parent Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Monday, 1 February 2021 at 10:27:29 UTC, Jacob Carlborg wrote:
 Why isn't

     "Name " ~ name ~ " could not be found"

 implicitly convertible to `string`?
Because if you have arrays of reference types, it's possible to change an element of the mutable array, which will affect the immutable array, those breaking the immutability. Example:
I still don't understand why that restriction applies to arrays of values types (such as `char`). Having this limitation makes my code example more bloated or less efficient memorywise; I either have to define two separate ctors or force an .idup at the site of the exception construction.
Feb 01
prev sibling next sibling parent reply ag0aep6g <anonymous example.com> writes:
On 31.01.21 22:48, Per Nordlöw wrote:
 Why isn't
 
      "Name " ~ name ~ " could not be found"
 
 implicitly convertible to `string`?
If concatenation is guaranteed to allocate a new array, then it should be "strongly pure", and the conversion should work. I'm not sure if it is guaranteed to allocate a new array.
 Would
 
 class NameLookupException : Exception
 {
      this(scope const(char)[] name)  trusted {
          super("Name " ~ cast(string)name ~ " could not be found");
      }
 }
 
 be ok?
Only if you know for sure that you're dealing with a compiler bug here. As another workaround, you can use std.conv.text: import std.conv: text; super(text("Name ", name, " could not be found"));
Feb 01
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/1/21 7:17 AM, ag0aep6g wrote:
 On 31.01.21 22:48, Per Nordlöw wrote:
 Why isn't

      "Name " ~ name ~ " could not be found"

 implicitly convertible to `string`?
If concatenation is guaranteed to allocate a new array, then it should be "strongly pure", and the conversion should work. I'm not sure if it is guaranteed to allocate a new array.
It is. https://dlang.org/spec/arrays.html#array-concatenation "Concatenation always creates a copy of its operands, even if one of the operands is a 0 length array" -Steve
Feb 01
parent reply Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Monday, 1 February 2021 at 15:47:33 UTC, Steven Schveighoffer 
wrote:
 "Concatenation always creates a copy of its operands, even if 
 one of the operands is a 0 length array"
Btw, does x ~ y ~ z ~ ... result in a single allocation?
Feb 01
parent reply Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Monday, 1 February 2021 at 16:30:31 UTC, Per Nordlöw wrote:
 Btw, does

     x ~ y ~ z ~ ...

 result in a single allocation?
Provided all the operands has a `length` property.
Feb 01
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 2/1/21 11:31 AM, Per Nordlöw wrote:
 On Monday, 1 February 2021 at 16:30:31 UTC, Per Nordlöw wrote:
 Btw, does

     x ~ y ~ z ~ ...

 result in a single allocation?
Provided all the operands has a `length` property.
As long as they are all arrays, yes, the compiler calls a single runtime call to concatenate all of them. For custom types, it's going to do them in order, 2 at a time. -Steve
Feb 01
prev sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 1/31/21 4:48 PM, Per Nordlöw wrote:

 Why isn't
 
      "Name " ~ name ~ " could not be found"
 
 implicitly convertible to `string`?
One of my oldest Enhancement requests: https://issues.dlang.org/show_bug.cgi?id=1654 -Steve
Feb 01