Re: Cannot implicitly convert expression of type const(string[]) to string[]

2021-01-08 Thread tsbockman via Digitalmars-d-learn

On Saturday, 9 January 2021 at 02:07:50 UTC, Ali Çehreli wrote:

The destination is immutable(char)[].


No, it's not. string[] means immutable(char)[][] - note the 
second set of brackets.


Even though the source is 'const ref', other.text is a copy of 
the slice object (the pointer and the length). Because the 
elements are immutable, other.text cannot mutate value.text.


The elements are not immutable. Each element is an mutable slice 
of immutable characters.



> Your code has a logical inconsistency

I don't see where. I think this is one of those too strict 
cases of D where I unhappily slap a cast and move on.


The cast you propose breaks the type system. For example:

module app;

import std.stdio;

struct Value
{
int value;
string data;
string[] text;
}

void test(const ref Value value) @trusted // Don't do this!
{
Value other = void;
other.text = cast(string[]) value.text; // This cast is 
@system for good reason.

other.text[0] = "Oops";
}

void main() @safe
{
immutable(Value) row = {
value: 10,
data: "ggg",
text: [ "Don't change me, bro!" ]
};

writeln(row.text);
test(row);
writeln(row.text);
}



Re: Cannot implicitly convert expression of type const(string[]) to string[]

2021-01-08 Thread Paul Backus via Digitalmars-d-learn

On Saturday, 9 January 2021 at 02:07:50 UTC, Ali Çehreli wrote:

On 1/8/21 3:10 PM, tsbockman wrote:

> On Friday, 8 January 2021 at 20:43:37 UTC, Andrey wrote:
>> Hello,
>>
>>> struct Value
>>> {
>>> int value;
>>> string data;
>>> string[] text;

The destination is immutable(char)[]. The characters cannot be 
changed. We can still append but other slices that share the 
same data is protected by D's no-stomp decision.


>>> }
>>>
>>> void test(const ref Value value)
>>> {
>>> Value other = void;
>>> other.text = value.text;

Even though the source is 'const ref', other.text is a copy of 
the slice object (the pointer and the length). Because the 
elements are immutable, other.text cannot mutate value.text.


Remember, `string[]` means `immutable(char)[][]`, so there are 
actually two layers of pointer + length here. The outer one is 
copied, but the inner one is not, which means that mutating 
`other.text[0]` would also mutate `value.text[0]` if this 
assignment were allowed.


Re: Cannot implicitly convert expression of type const(string[]) to string[]

2021-01-08 Thread Ali Çehreli via Digitalmars-d-learn

On 1/8/21 3:10 PM, tsbockman wrote:

> On Friday, 8 January 2021 at 20:43:37 UTC, Andrey wrote:
>> Hello,
>>
>>> struct Value
>>> {
>>> int value;
>>> string data;
>>> string[] text;

The destination is immutable(char)[]. The characters cannot be changed. 
We can still append but other slices that share the same data is 
protected by D's no-stomp decision.


>>> }
>>>
>>> void test(const ref Value value)
>>> {
>>> Value other = void;
>>> other.text = value.text;

Even though the source is 'const ref', other.text is a copy of the slice 
object (the pointer and the length). Because the elements are immutable, 
other.text cannot mutate value.text.


>>> }
>>>
>>> void main()
>>> {
>>> Value row;
>>> row.value = 10;
>>> row.data = "ggg";
>>>
>>> test(row);
>>> }

> Your code has a logical inconsistency

I don't see where. I think this is one of those too strict cases of D 
where I unhappily slap a cast and move on.


Ali



Re: Cannot implicitly convert expression of type const(string[]) to string[]

2021-01-08 Thread tsbockman via Digitalmars-d-learn

On Friday, 8 January 2021 at 23:10:13 UTC, tsbockman wrote:
5) Tell the compiler that `other.text` may be used to 
mutate `row.text` by `const` from the `value` parameter of 
`test`. Do not do this unless that's really what you want!


Oops, that should say:

5) Tell the compiler that `other.text` may be used to  mutate 
`row.text` by *removing* `const` from the `value` parameter of 
`test`. Do not do this unless that's really what you want!


Re: Cannot implicitly convert expression of type const(string[]) to string[]

2021-01-08 Thread tsbockman via Digitalmars-d-learn

On Friday, 8 January 2021 at 20:43:37 UTC, Andrey wrote:

Hello,


struct Value
{
int value;
string data;
string[] text;
}

void test(const ref Value value)
{
Value other = void;
other.text = value.text;
}

void main()
{
Value row;
row.value = 10;
row.data = "ggg";

test(row);
}


I want to pass variable "row" inside function "test" as a read 
only parameter.

Inside I create another variable and try to assign field "text".
On that line I get:
Error: cannot implicitly convert expression value.text of type 
const(string[]) to string[].


1. How to assign correctly (and without dup/ugly cast())?
2. Or how to pass "row" correctly?


Your code has a logical inconsistency which the compiler has 
rightly detected and flagged for you. You should actually fix the 
inconsistency, not just shut the compiler up.


If the compiler accepted your code, it would be possible to later 
modify the array pointed at by `row.text` through `other.text`, 
because `other.text` is not `const`. This would violate your 
stated desire to pass `row` as read-only.


There are various ways you can fix this, depending on your needs:
1) Change the type of `other` to `const(Value)` so that 
`other.text` cannot be used to modify `row.text`.
2) Change the type of `Value.text` to `const(string[])` so 
that it cannot be used to modify `row.text`.
3) Assign a copy (`dup`) of `row.text` to `other.text` 
instead, so that mutating the array pointed to by `other.text` 
will not modify the original read-only `row`.

4) Implement a copy-on-write scheme for `Value.text`.
5) Tell the compiler that `other.text` may be used to mutate 
`row.text` by `const` from the `value` parameter of `test`. Do 
not do this unless that's really what you want!


(1) and (2) are good options, if their limitations happen to fit 
whatever you're really doing. (Note that either requires you to 
write a constructor for `Value` since you won't be able to 
directly write to `Value.text` anymore.)


Unless you are managing huge quantities of data with this `Value` 
type, (3) is a perfectly reasonable thing to do and you shouldn't 
feel guilty about the small "waste" of memory and CPU time for 
the extra allocation. (4) is an option of last resort - not a 
crazy one, but not worth the trouble if the amount of data is 
small relative to system resources and/or the other activities of 
the program.


(5) is simple but WRONG unless you are trying to create multiple 
references to the same mutable data.


Re: Cannot implicitly convert expression of type const(string[]) to string[]

2021-01-08 Thread kdevel via Digitalmars-d-learn

On Friday, 8 January 2021 at 20:43:37 UTC, Andrey wrote:

[...]


2. Or how to pass "row" correctly?


Drop the "const" before "ref".




Cannot implicitly convert expression of type const(string[]) to string[]

2021-01-08 Thread Andrey via Digitalmars-d-learn

Hello,


struct Value
{
int value;
string data;
string[] text;
}

void test(const ref Value value)
{
Value other = void;
other.text = value.text;
}

void main()
{
Value row;
row.value = 10;
row.data = "ggg";

test(row);
}


I want to pass variable "row" inside function "test" as a read 
only parameter.

Inside I create another variable and try to assign field "text".
On that line I get:
Error: cannot implicitly convert expression value.text of type 
const(string[]) to string[].


1. How to assign correctly (and without dup/ugly cast())?
2. Or how to pass "row" correctly?