Thread overview | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
January 31, 2021 Type of string literal concatenated with non-immutable char array | ||||
---|---|---|---|---|
| ||||
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? |
February 01, 2021 Re: Type of string literal concatenated with non-immutable char array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Per Nordlöw | 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
|
February 01, 2021 Re: Type of string literal concatenated with non-immutable char array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jacob Carlborg | 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.
|
February 01, 2021 Re: Type of string literal concatenated with non-immutable char array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Per Nordlöw | 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")); |
February 01, 2021 Re: Type of string literal concatenated with non-immutable char array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Per Nordlöw | 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 |
February 01, 2021 Re: Type of string literal concatenated with non-immutable char array | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | 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 |
February 01, 2021 Re: Type of string literal concatenated with non-immutable char array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | 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?
|
February 01, 2021 Re: Type of string literal concatenated with non-immutable char array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Per Nordlöw | 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.
|
February 01, 2021 Re: Type of string literal concatenated with non-immutable char array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Per Nordlöw | 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
|
Copyright © 1999-2021 by the D Language Foundation