Re: AA and struct with const member

2021-12-29 Thread Era Scarecrow via Digitalmars-d-learn
On Wednesday, 29 December 2021 at 01:11:13 UTC, Stanislav Blinov 
wrote:
Because opIndexAssign cannot distinguish at compile time 
between initialization and assignment:


```d
Stuff[Key] aa;
aa[key] = Stuff(args); // ostensibly, initialization
aa[key] = otherStuff;  // assignment to existing value
```

Same syntax, different behavior. This can only be caught at 
runtime. `require` and `update` though should be able to pull 
this off, and that they don't is a bug.


So i wonder if const and immutable would have different behaviors 
then.


While you shouldn't be able to explicitly change a const item 
within a struct, replacing the whole struct i would think would 
be okay, on the basis that you're basically throwing whole old 
item away (*and may be equal to what you'd do with say swap*).


 Immutable on the other hand may want to refuse as it should 
basically have a lifetime of the array? Though if you can delete 
the item and then just add it in again it's a longer version of 
the same thing, just depends on if anything is using/referencing 
it or not. And casting away the constness is easy enough so maybe 
it won't be different.


 Though if it's a basic type it seems unlikely it would need a 
longer lifetime, and if it's a reference or array it already is 
separated from the struct and needs no such protection for the 
pointer.


 I don't know. I remember odd behavior with const/non-const stuff 
before.


Re: AA and struct with const member

2021-12-28 Thread Stanislav Blinov via Digitalmars-d-learn

On Wednesday, 29 December 2021 at 02:33:08 UTC, frame wrote:
On Wednesday, 29 December 2021 at 01:11:13 UTC, Stanislav 
Blinov wrote:


Because opIndexAssign cannot distinguish at compile time 
between initialization and assignment:


```d
Stuff[Key] aa;
aa[key] = Stuff(args); // ostensibly, initialization
aa[key] = otherStuff;  // assignment to existing value
```

Same syntax, different behavior. This can only be caught at 
runtime. `require` and `update` though should be able to pull 
this off, and that they don't is a bug.


Of course but opIndexAssign() isn't there in my example. The 
compiler should call runtime's _aaGetY() or something like that 
directly.


It is doing that. You've asked why that should be compile error, 
and the answer is - because there's no way to distinguish between 
initialization and assignment here. I.e. you can't make one line 
compile and the other - not. Either both compile, or both don't. 
So if you allow them to compile, you'll have to have a runtime 
check, throwing an exception on attempt to assign. Which is just 
horrible. Better to leave the assignment a compile error, and 
make `require` and `update` do the job they're supposed to be 
doing.


Re: AA and struct with const member

2021-12-28 Thread frame via Digitalmars-d-learn
On Wednesday, 29 December 2021 at 01:11:13 UTC, Stanislav Blinov 
wrote:


Because opIndexAssign cannot distinguish at compile time 
between initialization and assignment:


```d
Stuff[Key] aa;
aa[key] = Stuff(args); // ostensibly, initialization
aa[key] = otherStuff;  // assignment to existing value
```

Same syntax, different behavior. This can only be caught at 
runtime. `require` and `update` though should be able to pull 
this off, and that they don't is a bug.


Of course but opIndexAssign() isn't there in my example. The 
compiler should call runtime's _aaGetY() or something like that 
directly.





Re: AA and struct with const member

2021-12-28 Thread Stanislav Blinov via Digitalmars-d-learn

On Tuesday, 28 December 2021 at 22:46:16 UTC, frame wrote:

On Tuesday, 28 December 2021 at 10:02:13 UTC, tsbockman wrote:


  // Should be a compile-time error, because it might reassign:
  test[key] = S(value);


This might be a typo in your example but why should it be a 
compile-time error, it cannot know if the key already exists in 
compile time on a variable. First time initialization should 
always work anyway.


Because opIndexAssign cannot distinguish at compile time between 
initialization and assignment:


```d
Stuff[Key] aa;
aa[key] = Stuff(args); // ostensibly, initialization
aa[key] = otherStuff;  // assignment to existing value
```

Same syntax, different behavior. This can only be caught at 
runtime. `require` and `update` though should be able to pull 
this off, and that they don't is a bug.


Re: AA and struct with const member

2021-12-28 Thread frame via Digitalmars-d-learn

On Tuesday, 28 December 2021 at 10:02:13 UTC, tsbockman wrote:


  // Should be a compile-time error, because it might reassign:
  test[key] = S(value);


This might be a typo in your example but why should it be a 
compile-time error, it cannot know if the key already exists in 
compile time on a variable. First time initialization should 
always work anyway.


`require` and `update` can be fixed rather easily in 
`object.d`; I have submitted [issue 
22633](https://issues.dlang.org/show_bug.cgi?id=22633) with 
sample code.


Perfect. Thank you.




Re: AA and struct with const member

2021-12-28 Thread frame via Digitalmars-d-learn

On Tuesday, 28 December 2021 at 14:48:24 UTC, Era Scarecrow wrote:

 Probably better to make data private vs making it const. I 
tend to use const far more as input arguments to help denote it 
won't change references and less for elements in a struct. That 
or make it a class? I'm not sure.


It's a matter of consistency - if a function returns something in 
const one should be able to store it without any type 
modification.


Re: AA and struct with const member

2021-12-28 Thread Era Scarecrow via Digitalmars-d-learn

On Tuesday, 28 December 2021 at 07:51:04 UTC, frame wrote:
On Tuesday, 28 December 2021 at 01:45:42 UTC, Era Scarecrow 
wrote:



 Success!

 So i summarize, either work with a pointer, or drop the 
const...


Of course casting the const away was the first thing I did but 
I think this is not very clean :D


Well the next step up would be if the key does exist, you could 
then memcpy the result... which can have issues with non-native 
basic types.


 Probably better to make data private vs making it const. I tend 
to use const far more as input arguments to help denote it won't 
change references and less for elements in a struct. That or make 
it a class? I'm not sure.


Re: AA and struct with const member

2021-12-28 Thread tsbockman via Digitalmars-d-learn

On Tuesday, 28 December 2021 at 07:54:56 UTC, frame wrote:

On Tuesday, 28 December 2021 at 06:38:03 UTC, Tejas wrote:
The workaround is okay, but I think we should file a bug 
report for this.

This is very ~~stupid~~ undesirable behaviour


I agree. I'll just wait if somebody can explain why this isn't 
a bug or wanted behaviour or a known issue.


[The spec 
says](https://dlang.org/spec/hash-map.html#construction_assignment_entries):

```
2. If the assigned value type is equivalent with the AA element 
type:


1. If the indexing key does not yet exist in AA, a new AA 
entry will be allocated, and it will be initialized with the 
assigned value.
2. If the indexing key already exists in the AA, the setting 
runs normal assignment.

```
Thus, when the value type is constructable but not assignable:
```d
struct S
{
  const(int) a;
}

void test(S[string] aa, string key, int value)
{
  // Should be a compile-time error, because it might reassign:
  test[key] = S(value);

  // Should be accepted, because they can be proven at compile 
time to never reassign:

  test.require("a", S(value));
  test.update("a", () => S(value), (ref const(S)) => { });
}
```

`require` and `update` can be fixed rather easily in `object.d`; 
I have submitted [issue 
22633](https://issues.dlang.org/show_bug.cgi?id=22633) with 
sample code.


Re: AA and struct with const member

2021-12-27 Thread frame via Digitalmars-d-learn

On Tuesday, 28 December 2021 at 01:45:42 UTC, Era Scarecrow wrote:


 Success!

 So i summarize, either work with a pointer, or drop the 
const...


Of course casting the const away was the first thing I did but I 
think this is not very clean :D




Re: AA and struct with const member

2021-12-27 Thread frame via Digitalmars-d-learn

On Tuesday, 28 December 2021 at 06:38:03 UTC, Tejas wrote:
On Tuesday, 28 December 2021 at 01:45:42 UTC, Era Scarecrow 
wrote:

On Monday, 27 December 2021 at 19:38:38 UTC, frame wrote:

[...]


const/immutable members are to be set/assigned instantiation. 
Most likely the problem is a bug and sounds like


[...]


The workaround is okay, but I think we should file a bug report 
for this.

This is very ~~stupid~~ undesirable behaviour


I agree. I'll just wait if somebody can explain why this isn't a 
bug or wanted behaviour or a known issue.


Re: AA and struct with const member

2021-12-27 Thread Tejas via Digitalmars-d-learn

On Tuesday, 28 December 2021 at 01:45:42 UTC, Era Scarecrow wrote:

On Monday, 27 December 2021 at 19:38:38 UTC, frame wrote:

[...]


const/immutable members are to be set/assigned instantiation. 
Most likely the problem is a bug and sounds like


[...]


The workaround is okay, but I think we should file a bug report 
for this.

This is very ~~stupid~~ undesirable behaviour


Re: AA and struct with const member

2021-12-27 Thread Era Scarecrow via Digitalmars-d-learn

On Monday, 27 December 2021 at 19:38:38 UTC, frame wrote:
I feel stupid right now: One cannot assign a struct that 
contains const member to AA?


Error: cannot modify struct instance ... of type ... because it 
contains `const` or `immutable` members


This is considered a modification?
```d
struct S
{
  const(int) a;
}

S[string] test;
test["a"] = S(1);
```

Whats the workaround for that?


const/immutable members are to be set/assigned instantiation. 
Most likely the problem is a bug and sounds like


a) the struct doesn't exist in the AA, so it creates it (with a 
default)

b) It tries to copy but contains a const and thus fails

Passing a pointer will do you no good, since structs are likely 
to be on the stack.


So let's try opAssign.

```d
  auto ref opAssign(S s) {
this=s;
return this;
  }
```

So we get
```
'cannot modify struct instance `this` of type `S` because it 
contains `const` or `immutable` members'.

```

Alright let's look at the members we can work with.
https://dlang.org/spec/hash-map.html

I don't see an 'add' but i do see a 'require' which will add 
something in. So we try that.


test.require("a", S(1));

```
Now we get:
Error: cannot modify struct instance `*p` of type `S` because it 
contains `const` or `immutable` members
test.d(??): Error: template instance `object.require!(string, S)` 
error instantiating

```

Hmmm it really doesn't like it. Finally we can fake it. Let's 
make a mirror struct without the const, for the purposes of 
adding it.


```d
struct S
{
  const(int) a;
}

struct S2
{
  int a;
}

S[string] test;
cast(S2[string])test = S2(1);
```
```
Error: `cast(S2[string])test` is not an lvalue and cannot be 
modified

```

Well that's not going to work. Let's make it a pointer and 
allocate it instead.


```d
S*[string] test;
test["a"] = new S(1);
```

 Success!

 So i summarize, either work with a pointer, or drop the const...


AA and struct with const member

2021-12-27 Thread frame via Digitalmars-d-learn
I feel stupid right now: One cannot assign a struct that contains 
const member to AA?


Error: cannot modify struct instance ... of type ... because it 
contains `const` or `immutable` members


This is considered a modification?
```d
struct S
{
  const(int) a;
}

S[string] test;
test["a"] = S(1);
```

Whats the workaround for that?