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: Is there a way to make a function parameter accept only values that can be checked at compile time?

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

On Tuesday, 28 December 2021 at 22:30:30 UTC, Ali Çehreli wrote:

On 12/28/21 2:06 PM, Steven Schveighoffer wrote:


   void print_num(int mul)(int num) {


Wasn't there a way of telling whether an 'auto ref' parameter 
is copied or not?


void print_num()(int num, auto ref int mul) {
  // ?
}

And that would indicate  that the argument was an rvalue?


__traits(isRef, mul).

I realize that rvalues are not exactly what the OP is 
interested in.


Yup, different thing.

One can also do this kind of stuff:


```d
import core.stdc.stdio;

struct Literal(alias val)
{
enum value = val;
}

enum lit(alias val) = Literal!val.init;

void print_num(Arg)(int num, Arg mul)
{
static if (is(Arg == Literal!val, alias val))
{
static if (is(typeof(val) == string))
printf("mul by compile-time string \"%s\"!\n", 
val.ptr);

else static if (is(typeof(val) == int) && (val == 3))
printf("mul by compile-time 3!\n");
else
printf("mul by compile-time thing\n");
}
else
{
printf("mul by runtime thing\n");
}
}

void main()
{
print_num(10, lit!"hello"); // mul by compile-time string 
"hello"!

print_num(10, lit!3);   // mul by compile-time 3!
print_num(10, lit!'a'); // mul by compile-time thing
print_num(10, 10);  // mul by runtime thing
}
```


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: opCast + dtor error

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

On Tuesday, 28 December 2021 at 18:27:36 UTC, vit wrote:

Hi, why this code doesn't compile?

```d
struct Foo{
bool opCast(T : bool)()const{
assert(0);
}

~this(){}
}

struct Bar{
const Foo foo;
}

void main(){


}
```

Error: template instance `opCast!(Foo)` does not match template 
declaration `opCast(T : bool)()`


Since a destructor ignores `const`, I think adding the `~this` to 
Foo manually is somehow making the compiler have to actually cast 
away const, which it is doing via `cast(Foo) foo`, which fails 
since you've declared your own `opCast` that only accepts 
arguments implicitly convertible to `bool`.


I say this because removing the specialisation in `opCast` and 
changing the return type of it to `Foo` works :


```d
struct Foo{
Foo opCast(T)()const {
assert(0);
return this;
}
~this() {}

}

struct Bar{
const Foo foo;

}

void main(){
//Bar bar = Bar(); //this will trigger the assertion failure


}
```


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: Is there a way to make a function parameter accept only values that can be checked at compile time?

2021-12-28 Thread Ali Çehreli via Digitalmars-d-learn

On 12/28/21 2:06 PM, Steven Schveighoffer wrote:


   void print_num(int mul)(int num) {


Wasn't there a way of telling whether an 'auto ref' parameter is copied 
or not?


void print_num()(int num, auto ref int mul) {
  // ?
}

And that would indicate  that the argument was an rvalue?

I realize that rvalues are not exactly what the OP is interested in.

Ali



Re: Is there a way to make a function parameter accept only values that can be checked at compile time?

2021-12-28 Thread max haughton via Digitalmars-d-learn

On Tuesday, 28 December 2021 at 21:19:29 UTC, rempas wrote:
I would like to know if that's possible. Actually I would like 
to do something like the following:


```
extern (C) void main() {
  void print_num(int num, comp_time_type int mul) {
static if (is(mul == ten)) {
  printf("%d\n", num * 10);
} else static if (is(mul == three)) {
  printf("%d\n", num * 3);
} else {
  printf("%d\n", num);
}
  }

  int multi = 211;
  print_num(10, 3); // Ok, accept this
  print_num(10, multi); // Error, do not accept this
}
```

So I want to have "mul" only accept values that can be 
calculate at compile time so I can use it with things like 
"static if". Is this possible?


Why do you need this? What's wrong with a normal branch in this 
case.


Re: Is there a way to make a function parameter accept only values that can be checked at compile time?

2021-12-28 Thread Steven Schveighoffer via Digitalmars-d-learn

On 12/28/21 4:19 PM, rempas wrote:

Here:


```
extern (C) void main() {
   void print_num(int mul)(int num) {
     static if (is(mul == ten)) {
   printf("%d\n", num * 10);
     } else static if (is(mul == three)) {
   printf("%d\n", num * 3);
     } else {
   printf("%d\n", num);
     }
   }

   int multi = 211;
   print_num!3(10); // Ok, accept this
   print_num!multi(10); // Error, do not accept this
}
```


-Steve


Re: Is there a way to make a function parameter accept only values that can be checked at compile time?

2021-12-28 Thread Tobias Pankrath via Digitalmars-d-learn

On Tuesday, 28 December 2021 at 21:19:29 UTC, rempas wrote:
I would like to know if that's possible. Actually I would like 
to do something like the following:


```
extern (C) void main() {
  void print_num(int num, comp_time_type int mul) {
static if (is(mul == ten)) {
  printf("%d\n", num * 10);
} else static if (is(mul == three)) {
  printf("%d\n", num * 3);
} else {
  printf("%d\n", num);
}
  }

  int multi = 211;
  print_num(10, 3); // Ok, accept this
  print_num(10, multi); // Error, do not accept this
}
```

So I want to have "mul" only accept values that can be 
calculate at compile time so I can use it with things like 
"static if". Is this possible?


I think you have to make 'mul' a template parameter.


Is there a way to make a function parameter accept only values that can be checked at compile time?

2021-12-28 Thread rempas via Digitalmars-d-learn
I would like to know if that's possible. Actually I would like to 
do something like the following:


```
extern (C) void main() {
  void print_num(int num, comp_time_type int mul) {
static if (is(mul == ten)) {
  printf("%d\n", num * 10);
} else static if (is(mul == three)) {
  printf("%d\n", num * 3);
} else {
  printf("%d\n", num);
}
  }

  int multi = 211;
  print_num(10, 3); // Ok, accept this
  print_num(10, multi); // Error, do not accept this
}
```

So I want to have "mul" only accept values that can be calculate 
at compile time so I can use it with things like "static if". Is 
this possible?


Re: Starting and managing threads

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

Thanks! It works.
Perhaps there will still be difficulties, I will write here.


opCast + dtor error

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

Hi, why this code doesn't compile?

```d
struct Foo{
bool opCast(T : bool)()const{
assert(0);
}

~this(){}
}

struct Bar{
const Foo foo;
}

void main(){


}
```

Error: template instance `opCast!(Foo)` does not match template 
declaration `opCast(T : bool)()`






Re: Starting and managing threads

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

On Tuesday, 28 December 2021 at 16:29:05 UTC, Bagomot wrote:

I can't do it according to your example, my Watcher list fills 
up at runtime.


Yes, it's possible to do it at runtime as well(it already _was_ 
happening at runtime), although I'll be using a `cast` for 
convenience now.


```d
import std.concurrency;
import core.thread;
import std.stdio:writeln,readf;
void main() {
  writeln("Please enter num of elements");
  int a;
  readf!"%d"(a);
  foreach(number; 0..a){
Test.getInstance.watchers ~= new Watcher();//will have to use 
operations from core.atomic if you want to read/write shared 
variables, that's why I didn't declare the array as shared

  }
Test.getInstance.run;
}

class Test {
private {
__gshared Test instance;
/+shared+/ Watcher[] watchers;
}

protected this() {
}

public static Test getInstance() {
if (!instance) {
synchronized (Test.classinfo) {
if (!instance)
instance = new Test;
}
}

return instance;
}

public void run() {
		foreach (ref watcher; cast(shared)/+using cast so that TLS gets 
disabled)+/this.watchers) {

spawn(, watcher);
}
}
}

class Watcher {
static public void run(shared Watcher watcher) {
while (true) {
// job
  writeln("It works now :D");
  break;
}
}
}
```


Re: Starting and managing threads

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

On Tuesday, 28 December 2021 at 15:42:04 UTC, Tejas wrote:

On Tuesday, 28 December 2021 at 14:19:46 UTC, Bagomot wrote:

On Monday, 27 December 2021 at 10:59:07 UTC, Ali Çehreli wrote:

On 12/27/21 1:33 AM, Bagomot wrote:

> separate thread, without blocking the main one.

I think you can use std.concurrency there. I have a chapter 
here:


  http://ddili.org/ders/d.en/concurrency.html

Look for 'struct Exit' to see how the main thread signals 
workers to stop running.


And some std.concurrency hints appear in my DConf Online 2020 
presentation here:


  https://dconf.org/2020/online/#ali1

Ali


I tried to run with std.concurrency via spawn, but this does 
not work for me for the reason that in the program I run the 
thread not from main, but from the object. It looks something 
like this:


```d
import std.concurrency;
import std.thread;

void main() {
Test.getInstance.run;
}

class Test {
private {
__gshared Test instance;
Watcher[] watchers;
}

protected this() {
}

public static Test getInstance() {
if (!instance) {
synchronized (Test.classinfo) {
if (!instance)
instance = new Test;
}
}

return instance;
}

public void run() {
foreach (Watcher watcher; this.watchers) {
spawn();
}
}
}

class Watcher {
public void run() {
while (true) {
// job
}
}
}
```
Error: template `std.concurrency.spawn` cannot deduce function 
from argument types `!()(void delegate())`.


I would not want to do this from main because it breaks the 
structure of my program. Is there a way to do it the way I 
want?



Yes, you'll have to make the function that you want to run 
static and all the arguments must be `shared` qualified, ie, 
TLS not allowed

```d

import std.concurrency;
import core.thread;
import std.stdio:writeln;

void main() {
Test.getInstance.run;
}

class Test {
private {
__gshared Test instance;
		shared Watcher[] watchers = [new Watcher(), new Watcher()]; 
//notice the shared // I used 2 values just to show some output

}

protected this() {
}

public static Test getInstance() {
if (!instance) {
synchronized (Test.classinfo) {
if (!instance)
instance = new Test;
}
}

return instance;
}

public void run() {
		foreach (ref/+use ref to ensure no copies are made. I don't 
tknow the right thing to do here, the errors went away when I 
used ref so...+/ watcher; this.watchers) {

spawn(, watcher);
}
}
}

class Watcher {
	static public void run(shared Watcher watcher/+sending as 
argument since function can't have an invisible this parameter 
anymore+/) {//now this is static

while (true) {
// job
  writeln("It works now :D");
  break; //wrote this so that you can copy-paste to 
run.dlang.io

}
}
}
```


I can't do it according to your example, my Watcher list fills up 
at runtime.


Re: Starting and managing threads

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

On Tuesday, 28 December 2021 at 14:19:46 UTC, Bagomot wrote:

On Monday, 27 December 2021 at 10:59:07 UTC, Ali Çehreli wrote:

On 12/27/21 1:33 AM, Bagomot wrote:

> separate thread, without blocking the main one.

I think you can use std.concurrency there. I have a chapter 
here:


  http://ddili.org/ders/d.en/concurrency.html

Look for 'struct Exit' to see how the main thread signals 
workers to stop running.


And some std.concurrency hints appear in my DConf Online 2020 
presentation here:


  https://dconf.org/2020/online/#ali1

Ali


I tried to run with std.concurrency via spawn, but this does 
not work for me for the reason that in the program I run the 
thread not from main, but from the object. It looks something 
like this:


```d
import std.concurrency;
import std.thread;

void main() {
Test.getInstance.run;
}

class Test {
private {
__gshared Test instance;
Watcher[] watchers;
}

protected this() {
}

public static Test getInstance() {
if (!instance) {
synchronized (Test.classinfo) {
if (!instance)
instance = new Test;
}
}

return instance;
}

public void run() {
foreach (Watcher watcher; this.watchers) {
spawn();
}
}
}

class Watcher {
public void run() {
while (true) {
// job
}
}
}
```
Error: template `std.concurrency.spawn` cannot deduce function 
from argument types `!()(void delegate())`.


I would not want to do this from main because it breaks the 
structure of my program. Is there a way to do it the way I want?



Yes, you'll have to make the function that you want to run static 
and all the arguments must be `shared` qualified, ie, TLS not 
allowed

```d

import std.concurrency;
import core.thread;
import std.stdio:writeln;

void main() {
Test.getInstance.run;
}

class Test {
private {
__gshared Test instance;
		shared Watcher[] watchers = [new Watcher(), new Watcher()]; 
//notice the shared // I used 2 values just to show some output

}

protected this() {
}

public static Test getInstance() {
if (!instance) {
synchronized (Test.classinfo) {
if (!instance)
instance = new Test;
}
}

return instance;
}

public void run() {
		foreach (ref/+use ref to ensure no copies are made. I don't 
tknow the right thing to do here, the errors went away when I 
used ref so...+/ watcher; this.watchers) {

spawn(, watcher);
}
}
}

class Watcher {
	static public void run(shared Watcher watcher/+sending as 
argument since function can't have an invisible this parameter 
anymore+/) {//now this is static

while (true) {
// job
  writeln("It works now :D");
  break; //wrote this so that you can copy-paste to 
run.dlang.io

}
}
}
```


Re: How to print unicode characters (no library)?

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

On Tuesday, 28 December 2021 at 14:53:57 UTC, rempas wrote:
On Tuesday, 28 December 2021 at 12:56:11 UTC, Adam D Ruppe 
wrote:


https://invisible-island.net/xterm/ctlseqs/ctlseqs.html

and that's not quite full either. it really is a mess from 
hell


Still less complicated and organized than my life...


"Less complicated and more organized" is what I wanted to say. 
Damn I can't even make a joke right...


Re: How to print unicode characters (no library)?

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

On Tuesday, 28 December 2021 at 13:04:26 UTC, Adam D Ruppe wrote:
What is your library? You might be able to just use my 
terminal.d too


My library will be "libd" it will be like "libc" but better and 
cooler! And it will be native to D! And of course it will not 
depend on "libc" and it will not require and special runtime 
support as it will be "betterC". I don't plan to replace the 
other "default libs" like "libm", librt", "libpthread" etc. tho. 
At least not for now...


Virtually all of it; Windows is just way easier to develop for. 
You'll see if you get deeper in this terminal stuff reading 
mouse data from Windows is a simple read of input event 
structs. Doing it from a Linux system is... not simple.


Well sucks to be me


Re: How to print unicode characters (no library)?

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

On Tuesday, 28 December 2021 at 12:56:11 UTC, Adam D Ruppe wrote:


https://invisible-island.net/xterm/ctlseqs/ctlseqs.html

and that's not quite full either. it really is a mess from 
hell


Still less complicated and organized than my life...


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: Starting and managing threads

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

On Monday, 27 December 2021 at 10:59:07 UTC, Ali Çehreli wrote:

On 12/27/21 1:33 AM, Bagomot wrote:

> separate thread, without blocking the main one.

I think you can use std.concurrency there. I have a chapter 
here:


  http://ddili.org/ders/d.en/concurrency.html

Look for 'struct Exit' to see how the main thread signals 
workers to stop running.


And some std.concurrency hints appear in my DConf Online 2020 
presentation here:


  https://dconf.org/2020/online/#ali1

Ali


I tried to run with std.concurrency via spawn, but this does not 
work for me for the reason that in the program I run the thread 
not from main, but from the object. It looks something like this:


```d
import std.concurrency;
import std.thread;

void main() {
Test.getInstance.run;
}

class Test {
private {
__gshared Test instance;
Watcher[] watchers;
}

protected this() {
}

public static Test getInstance() {
if (!instance) {
synchronized (Test.classinfo) {
if (!instance)
instance = new Test;
}
}

return instance;
}

public void run() {
foreach (Watcher watcher; this.watchers) {
spawn();
}
}
}

class Watcher {
public void run() {
while (true) {
// job
}
}
}
```
Error: template `std.concurrency.spawn` cannot deduce function 
from argument types `!()(void delegate())`.


I would not want to do this from main because it breaks the 
structure of my program. Is there a way to do it the way I want?


Re: How to print unicode characters (no library)?

2021-12-28 Thread Adam D Ruppe via Digitalmars-d-learn

On Tuesday, 28 December 2021 at 06:51:52 UTC, rempas wrote:
That's pretty nice. In this case is even better because at 
least for now, I will not work on Windows by myself because 
making the library work on Linux is a bit of a challenge itself.


What is your library? You might be able to just use my terminal.d 
too


The Windows API is an absolute pleasure to work with next to 
much of the trash you're forced to deal with on Linux.


Wht??? Don't crash my dreams sempai!!! I mean, this may 
sound stupid but which kind of API you are referring to? Do you 
mean system library stuff (like "unistd.h" for linux and 
"windows.h" for Windows) or low level system calls?


Virtually all of it; Windows is just way easier to develop for. 
You'll see if you get deeper in this terminal stuff reading 
mouse data from Windows is a simple read of input event structs. 
Doing it from a Linux system is... not simple.


Re: How to print unicode characters (no library)?

2021-12-28 Thread Adam D Ruppe via Digitalmars-d-learn

On Tuesday, 28 December 2021 at 07:03:25 UTC, rempas wrote:
I already knew about some of this "escape codes" but I full 
list of them will come in handy ;)


https://invisible-island.net/xterm/ctlseqs/ctlseqs.html

and that's not quite full either. it really is a mess from 
hell


Re: How to print unicode characters (no library)?

2021-12-28 Thread Adam D Ruppe via Digitalmars-d-learn

On Tuesday, 28 December 2021 at 06:46:57 UTC, ag0aep6g wrote:
It's actually just the first byte that tells you how many are 
in the sequence. The continuation bytes don't have redundancies 
for that.


Right, but they do have that high bit set and next bit clear so 
you can tell you're in the middle and thus either go backward to 
the count byte to recover this character or go forward to the 
next count byte and drop this char while recovering the stream. 
My brain mixed this up with the rest of it and wrote it poorly 
lol.


Re: How to print unicode characters (no library)?

2021-12-28 Thread Patrick Schluter via Digitalmars-d-learn

On Monday, 27 December 2021 at 07:12:24 UTC, rempas wrote:


I don't understand that. Based on your calculations, the 
results should have been different. Also how are the numbers 
fixed? Like you said the amount of bytes of each encoding is 
not always standard for every character. Even if they were 
fixed this means 2-bytes for each UTF-16 character and 4-bytes 
for each UTF-32 character so still the numbers doesn't make 
sense to me. So still the number of the "length" property 
should have been the same for every encoding or at least for 
UTF-16 and UTF-32. So are the sizes of every character fixed or 
not?




Your string is represented by 8 codepoints. The number of 
codeunits to represent them in memory depends on the encoding. D 
supports to work with 3 different encodings (in the Unicode 
standard there are more than these 3)


string  utf8s  = "Hello \n";
wstring utf16s = "Hello \n"w;
dstring utf32s = "Hello \n"d;

Here the canonical Unicode representation of your string

   H  e  l  l  o  \n
U+0048 U+0065 U+006C U+006C U+006F U+0020 U+1F602 U+000a

let's see how these 3 variable are represented in memory:

utf8s : 48 65 6C 6C 6F 20 F0 9F 98 82 0a
11 char in memory using 11 bytes

utf16s: 0048 0065 006C 006C 006F 0020 D83D DE02 000A
9 wchar in memory using 18 bytes

utf16s: 0048 0065 006C 006C 006F 0020 
0001F602 000A

8 dchar in memory using 32 bytes

As you can see, the most compact form is generally UTF-8, that's 
why it is the preferred encoding for Unicode.


UTF-16 is supported because of legacy support reason like it is 
used in the Windows API and also internally in Java.


UTF-32 has one advantage, in that it has a 1 to 1 mapping between 
codepoint and array index. In practice it is not that much of an 
advantage as codepoints and characters are disjoint concepts. 
UTF-32 uses a lot of memory for practically no benefit (when you 
read in the forum about the big auto-decode error of D it is 
linked to this).


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.