Re: Mutate immutable inside shared static constructor

2024-03-24 Thread Menjanahary R. R. via Digitalmars-d-learn

On Saturday, 23 March 2024 at 21:59:57 UTC, Nick Treleaven wrote:
On Saturday, 23 March 2024 at 21:53:43 UTC, Jonathan M Davis 
wrote:
Yes, it's a bug. It's a clear violation of the type system if 
a non-mutable variable is ever given a value more than once. 
It should be initialized, and then it should be treated as 
illegal to ever assign to it - or to do anything else which 
would mutate it. So, clearly, the logic in static constructors 
with regards to non-mutable variables is overly simple at the 
moment.


Thanks, filed:
https://issues.dlang.org/show_bug.cgi?id=24449


Thanks for your prompt answer.


Re: Mutate immutable inside shared static constructor

2024-03-23 Thread Nick Treleaven via Digitalmars-d-learn
On Saturday, 23 March 2024 at 21:53:43 UTC, Jonathan M Davis 
wrote:
Yes, it's a bug. It's a clear violation of the type system if a 
non-mutable variable is ever given a value more than once. It 
should be initialized, and then it should be treated as illegal 
to ever assign to it - or to do anything else which would 
mutate it. So, clearly, the logic in static constructors with 
regards to non-mutable variables is overly simple at the moment.


Thanks, filed:
https://issues.dlang.org/show_bug.cgi?id=24449


Re: Mutate immutable inside shared static constructor

2024-03-23 Thread Jonathan M Davis via Digitalmars-d-learn
On Saturday, March 23, 2024 3:23:23 PM MDT Nick Treleaven via Digitalmars-d-
learn wrote:
> I've not used static constructors before, but it seems like the
> following should not be allowed:
>
> ```d
> import std.stdio;
>
> immutable int x;
>
> @safe shared static this()
> {
>  x.writeln(); // 0
>  x = 5;
>  x.writeln(); // 5
>  x = 6;
>  x++;
>  assert(x == 7);
> }
> ```
> Should I file a bug to require that `x` is only written to once?
> That would make it consistent with class constructors:
>
> ```d
> class C
> {
>  immutable int x;
>  this()
>  {
>  x = 5;
>  x = 6; // error, x initialized multiple times
>  }
> }
> ```

Yes, it's a bug. It's a clear violation of the type system if a non-mutable
variable is ever given a value more than once. It should be initialized, and
then it should be treated as illegal to ever assign to it - or to do
anything else which would mutate it. So, clearly, the logic in static
constructors with regards to non-mutable variables is overly simple at the
moment.

- Jonathan M Davis





Mutate immutable inside shared static constructor

2024-03-23 Thread Nick Treleaven via Digitalmars-d-learn
I've not used static constructors before, but it seems like the 
following should not be allowed:


```d
import std.stdio;

immutable int x;

@safe shared static this()
{
x.writeln(); // 0
x = 5;
x.writeln(); // 5
x = 6;
x++;
assert(x == 7);
}
```
Should I file a bug to require that `x` is only written to once? 
That would make it consistent with class constructors:


```d
class C
{
immutable int x;
this()
{
x = 5;
x = 6; // error, x initialized multiple times
}
}
```


Re: Implicit conversion of string to array of immutable ubytes

2024-03-23 Thread Jonathan M Davis via Digitalmars-d-learn
On Saturday, March 23, 2024 12:11:15 AM MDT Per Nordlöw via Digitalmars-d-
learn wrote:
> Why doesn't string implicitly convert to immutable(ubyte)[] in
> @safe mode?

Why would it? They're different types. Their elements happen to have the
same size, but that doesn't mean that they're used for the same thing at
all. And having them be implicitly convertible could cause serious problems
with overloading.

If you want to do that conversion without a cast, then you can just use
std.string.representation (which will do the cast internally).

- Jonathan M Davis






Re: std.string.assumeUTF() silently casting mutable to immutable?

2024-02-14 Thread RazvanN via Digitalmars-d-learn

On Wednesday, 14 February 2024 at 11:56:29 UTC, Forest wrote:

On Wednesday, 14 February 2024 at 10:57:42 UTC, RazvanN wrote:


This has already been fixed, you just need to use 
-preview=fixImmutableConv. This was put behind a preview flag 
as it introduces a breaking change.


I just tried that flag on run.dlang.org, and although it fixes 
the case I posted earlier, it doesn't fix this one:


```d
string test(const(ubyte)[] arr)
{
import std.string;
return arr.assumeUTF;
}
```

Shouldn't this be rejected as well?


Indeed, that should be rejected as well, otherwise you can modify 
immutable table. This code currently happily compiles:


```d
string test(const(ubyte)[] arr)
{
import std.string;
return arr.assumeUTF;
}

void main()
{
import std.stdio;
ubyte[] arr = ['a', 'b', 'c'];
auto t = test(arr);
writeln(t);
arr[0] = 'x';
writeln(t);
}
```

And prints:

```
abc
xbc
```

However, this seems to be a different issue.


Re: std.string.assumeUTF() silently casting mutable to immutable?

2024-02-14 Thread Forest via Digitalmars-d-learn

On Wednesday, 14 February 2024 at 10:57:42 UTC, RazvanN wrote:


This has already been fixed, you just need to use 
-preview=fixImmutableConv. This was put behind a preview flag 
as it introduces a breaking change.


I just tried that flag on run.dlang.org, and although it fixes 
the case I posted earlier, it doesn't fix this one:


```d
string test(const(ubyte)[] arr)
{
import std.string;
return arr.assumeUTF;
}
```

Shouldn't this be rejected as well?


Re: std.string.assumeUTF() silently casting mutable to immutable?

2024-02-13 Thread Forest via Digitalmars-d-learn

On Tuesday, 13 February 2024 at 14:05:03 UTC, Johan wrote:
On Tuesday, 13 February 2024 at 08:10:20 UTC, Jonathan M Davis 
wrote:


So, there's definitely a bug here, but it's a dmd bug. Its 
checks for whether it can safely change the constness of the 
return type apparently aren't sophisticated enough to catch 
this case.


This is a pretty severe bug.


Thanks, gents.

Reported on the tracker:

https://issues.dlang.org/show_bug.cgi?id=24394


Re: std.string.assumeUTF() silently casting mutable to immutable?

2024-02-13 Thread Johan via Digitalmars-d-learn
On Tuesday, 13 February 2024 at 08:10:20 UTC, Jonathan M Davis 
wrote:


So, there's definitely a bug here, but it's a dmd bug. Its 
checks for whether it can safely change the constness of the 
return type apparently aren't sophisticated enough to catch 
this case.


This is a pretty severe bug.
Some test cases: https://d.godbolt.org/z/K1fjdj76M
```d
ubyte[] pure_ubyte(ubyte[] arr) pure @safe;
ubyte[] pure_void(void[] arr) pure @safe;
ubyte[] pure_int(int[] arr) pure @safe;
int[] pure_ubyte_to_int(ubyte[] arr) pure @safe;

// All cases below should not compile, yet some do.

immutable(ubyte)[] test(ubyte[] arr) @safe
{
// return with_ubyte(arr); // ERROR: OK
return pure_void(arr); // No error: NOK!
}

immutable(ubyte)[] test(int[] arr) @safe
{
return pure_int(arr); // No error: NOK!
}

immutable(int)[] test2(ubyte[] arr) @safe
{
return pure_ubyte_to_int(arr); // No error: NOK!
}
```

-Johan




Re: std.string.assumeUTF() silently casting mutable to immutable?

2024-02-13 Thread Jonathan M Davis via Digitalmars-d-learn
On Tuesday, February 13, 2024 12:40:57 AM MST Forest via Digitalmars-d-learn 
wrote:
> I may have found a bug in assumeUTF(), but being new to D, I'm
> not sure.
>
> The description:
> > Assume the given array of integers arr is a well-formed UTF
> > string and return it typed as a UTF string.
> > ubyte becomes char, ushort becomes wchar and uint becomes
> > dchar. Type qualifiers are preserved.
>
> The declaration:
>
> ```d
> auto assumeUTF(T)(T[] arr)
> if (staticIndexOf!(immutable T, immutable ubyte, immutable
> ushort, immutable uint) != -1)
> ```
>
> Shouldn't that precondition's `immutable T` be simply `T`?
>
> As it stands, I can do this with no complaints from the
> compiler...
>
> ```d
> string test(ubyte[] arr)
> {
>  import std.string;
>  return arr.assumeUTF;
> }
>
> ```
>
> ...and accidentally end up with a "string" pointing at mutable
> data.
>
> Am I missing something?

It's not a bug in assumeUTF. if you changed your code to

string test(ubyte[] arr)
{
 import std.string;
 pragma(msg, typeof(arr.assumeUTF));
 return arr.assumeUTF;
}

then the compiler will output

char[]

because assumeUTF retains the type qualifier of the original type (as its
documentation explains). Rather, it looks like the problem here is that dmd
will implictly change the constness of a return value when it thinks that it
can do so to make the code work. Essentially, that means that the function
has to be pure and that the return value can't have come from any of the
function's arguments. And at a glance, that would be true here, because no
char[] was passed into assumeUTF. However, casting from ubyte[] to char[] is
@safe, so dmd should be taking that possibility into account, and it's
apparently not.

So, there's definitely a bug here, but it's a dmd bug. Its checks for
whether it can safely change the constness of the return type apparently
aren't sophisticated enough to catch this case.

- Jonathan M Davis





std.string.assumeUTF() silently casting mutable to immutable?

2024-02-12 Thread Forest via Digitalmars-d-learn
I may have found a bug in assumeUTF(), but being new to D, I'm 
not sure.


The description:

Assume the given array of integers arr is a well-formed UTF 
string and return it typed as a UTF string.
ubyte becomes char, ushort becomes wchar and uint becomes 
dchar. Type qualifiers are preserved.


The declaration:

```d
auto assumeUTF(T)(T[] arr)
if (staticIndexOf!(immutable T, immutable ubyte, immutable 
ushort, immutable uint) != -1)

```

Shouldn't that precondition's `immutable T` be simply `T`?

As it stands, I can do this with no complaints from the 
compiler...


```d
string test(ubyte[] arr)
{
import std.string;
return arr.assumeUTF;
}

```

...and accidentally end up with a "string" pointing at mutable 
data.


Am I missing something?


Re: On assigning const to immutable

2023-07-13 Thread FeepingCreature via Digitalmars-d-learn

On Thursday, 13 July 2023 at 11:55:17 UTC, Ki Rill wrote:
Why does the first example `class A` work, but the second one 
with `class B` does not?

```D
class A {
immutable int a;
this(in int a) {
this.a = a;
}
}

class B {
immutable int[] b;
this(in int[] b) {
this.b = b;
}
}

void main()
{
auto a = new A(1);
auto b = new B([1, 2]);
}
```

It implicitly converts `const` to `immutable`, but fails to do 
the same with an array. Is it intentional? Why?


Yep: `immutable` is data that *cannot ever* change. If you could 
convert `int[]` to `immutable int[]`, you could do this:


```
int[] a = [2];
immutable(int)[] b = a;

auto first = b[0];
a[0] = 3;
auto second = b[0];

// Wait, this fails? I thought `b` was immutable.
assert(first == second);
```

Use `array.idup` (immutable dup) to turn `int[]` into `immutable 
int[]`.


And you can convert `int` to `immutable int` because it's a 
"value copy": you cannot mutate the immutable variable through an 
assignment to the original. Generally speaking, only the 
constness of referenced data matters for assignment.


That's why you can assign `string` to `immutable string`, because 
`string` is `immutable(char)[]`: the referenced data is immutable 
in both cases.


Re: On assigning const to immutable

2023-07-13 Thread Ki Rill via Digitalmars-d-learn

On Thursday, 13 July 2023 at 11:55:17 UTC, Ki Rill wrote:
Why does the first example `class A` work, but the second one 
with `class B` does not?

```D
class A {
immutable int a;
this(in int a) {
this.a = a;
}
}

class B {
immutable int[] b;
this(in int[] b) {
this.b = b;
}
}

void main()
{
auto a = new A(1);
auto b = new B([1, 2]);
}
```

It implicitly converts `const` to `immutable`, but fails to do 
the same with an array. Is it intentional? Why?


Oh, is it because the first one is passed by value, but the 
second one is a reference?


On assigning const to immutable

2023-07-13 Thread Ki Rill via Digitalmars-d-learn
Why does the first example `class A` work, but the second one 
with `class B` does not?

```D
class A {
immutable int a;
this(in int a) {
this.a = a;
}
}

class B {
immutable int[] b;
this(in int[] b) {
this.b = b;
}
}

void main()
{
auto a = new A(1);
auto b = new B([1, 2]);
}
```

It implicitly converts `const` to `immutable`, but fails to do 
the same with an array. Is it intentional? Why?


Para que sirve o que son las variables "immutable"?

2023-06-15 Thread Danico via Digitalmars-d-learn
Tengo una duda y es que en la documentacion de std.json hay un 
ejemplo de codigo que por identidicador ponen "immutable", nose 
para que sirve o de que trata. :( alguien me diga porfis :)


Re: Code duplication where you wish to have a routine called with either immutable or mutable arguments

2023-05-31 Thread Cecil Ward via Digitalmars-d-learn

On Wednesday, 31 May 2023 at 09:14:49 UTC, Dom DiSc wrote:

On Wednesday, 31 May 2023 at 03:29:33 UTC, Cecil Ward wrote:
I have to admit that I don’t really understand immutable. I 
have an idea that it could mean that an object has an address 
in ROM, so its value will never change. Maybe const doesn’t 
give you such a strong guarantee, disallows ‘you’ from 
modifying it but others might do so, but who knows.
There are two perspectives: that of the value handed to a 
function and that of the function taking the value.
"immutable" (or "mutable") is a property of the value, "const" 
is a property of the function.
If the function can work with mutable values, but in fact 
doesn't mutate them itself, it could also work with immutable 
values. The fact that others could modify your "const" value 
doesn't matter for immutable values, because they of course 
can't be modified by others. For the function it doesn't 
matter, because it only guarantees not to modify it itself, 
don't care about what other can or can't do.



Without a guarantee as strong as the first idea I can’t really
understand how const can work properly. "You treat it as const
so do not modify it, but it might not be eternally fixed and
unchanging" that doesn’t seem to have enough value to me.

Why? What guarantee are you missing?
Your function can work with mutable data, so you don't care if 
it can be modified also by others.
Now it happens that you doesn't modify the data. So why 
shouldn't you be able to work on data that guarantees that it 
also will not be changed by others? You don't care for such 
modification anyway.


The meaning of "immutable" is: I cannot be modified. Not by you 
and not by anybody else. It's a property of a value.
The meaning of "mutable" is: I can be modified by anybody. Work 
with me only if that is ok for you. It's a property of a value.
The meaning of "const" is: I don't care if others modify the 
data or not, I won't modify it myself. It's a property of a 
function.


Dom, you explain it well. I’m just too stupid. Literally, as I’m 
on strong pain drugs all the time, so things are a bit fuzzy. As 
a professional C programmer for some years, I understood the word 
const and used it all the time, as much as possible at every 
opportunity, so I had some expectations. But the errors I’m 
getting don’t fit in with the previous understanding I had with 
the familiar ‘const’ keyword and make me think there must be 
something else going on. So I will need to capture an example in 
the wild, cage it and bring it in for scientific examination.


I can’t ask for an explanation of things going on that you can’t 
inspect for yourself, obviously. And I don’t understand what the 
problem is with using in as much as possible yet having to remove 
it sometimes when something immutable is in use.


Re: static immutable that has no initialiser - should this raise an error?

2023-05-31 Thread Dom DiSc via Digitalmars-d-learn

On Tuesday, 30 May 2023 at 04:11:00 UTC, Cecil Ward wrote:

static immutable T foo;

T bar() {
return foo;
}

Should we get an error from the D compiler here as the 
initialiser has been forgotten? What do you think ?

No.
There are no un-initialized values in D.
It gets its default value, if no explicit value is given.
That's intended, not an error.
If you need an un-initialized value, set it =void.
Of course, for immutable values that makes no sense at all.
But I think, this already gives you an error.



Re: Code duplication where you wish to have a routine called with either immutable or mutable arguments

2023-05-31 Thread Dom DiSc via Digitalmars-d-learn

On Wednesday, 31 May 2023 at 03:29:33 UTC, Cecil Ward wrote:
I have to admit that I don’t really understand immutable. I 
have an idea that it could mean that an object has an address 
in ROM, so its value will never change. Maybe const doesn’t 
give you such a strong guarantee, disallows ‘you’ from 
modifying it but others might do so, but who knows.
There are two perspectives: that of the value handed to a 
function and that of the function taking the value.
"immutable" (or "mutable") is a property of the value, "const" is 
a property of the function.
If the function can work with mutable values, but in fact doesn't 
mutate them itself, it could also work with immutable values. The 
fact that others could modify your "const" value doesn't matter 
for immutable values, because they of course can't be modified by 
others. For the function it doesn't matter, because it only 
guarantees not to modify it itself, don't care about what other 
can or can't do.



Without a guarantee as strong as the first idea I can’t really
understand how const can work properly. "You treat it as const
so do not modify it, but it might not be eternally fixed and
unchanging" that doesn’t seem to have enough value to me.

Why? What guarantee are you missing?
Your function can work with mutable data, so you don't care if it 
can be modified also by others.
Now it happens that you doesn't modify the data. So why shouldn't 
you be able to work on data that guarantees that it also will not 
be changed by others? You don't care for such modification anyway.


The meaning of "immutable" is: I cannot be modified. Not by you 
and not by anybody else. It's a property of a value.
The meaning of "mutable" is: I can be modified by anybody. Work 
with me only if that is ok for you. It's a property of a value.
The meaning of "const" is: I don't care if others modify the data 
or not, I won't modify it myself. It's a property of a function.




Re: Code duplication where you wish to have a routine called with either immutable or mutable arguments

2023-05-30 Thread Cecil Ward via Digitalmars-d-learn

On Wednesday, 31 May 2023 at 03:23:01 UTC, Cecil Ward wrote:

On Tuesday, 30 May 2023 at 04:15:22 UTC, Ali Çehreli wrote:

On 5/29/23 19:57, Cecil Ward wrote:

> I wish to have one routine
> that can be called with either immutable or (possibly)
mutable argument
> values.

'const' should take both immutable and mutable. Can you show 
your case with a short example?


> Could I make the one routine into a template?

That could work but give 'in' parameters a try:

  https://dlang.org/spec/function.html#in-params

Ali


T2 foo( in T1 x ) { return bar( x ) };

It was with something vaguely like the above that I had to 
remove the in (templatised generic function possibly) in order 
to get it to compile with GDC or LDC on godbolt.org (or 
d.godbolt.org) latest versions available. -O3 
-release/-frelease -march=native/-mcpu-native


I have to admit that I don’t really understand immutable. I have 
an idea that it could mean that an object has an address in ROM, 
so its value will never change. Maybe const doesn’t give you such 
a strong guarantee, disallows ‘you’ from modifying it but others 
might do so, but who knows. Without a guarantee as strong as the 
first idea I can’t really understand how const can work properly. 
"You treat it as const so do not modify it, but it might not be 
eternally fixed and  unchanging" that doesn’t seem to have enough 
value to me. But maybe I’ve got the whole thing wrong.


In an architecture where you have strongly typed (tagged ? 
segmented?) different kinds of addresses, I can see why you might 
be getting type mismatch errors when passing addresses around.


Re: Code duplication where you wish to have a routine called with either immutable or mutable arguments

2023-05-30 Thread Cecil Ward via Digitalmars-d-learn

On Tuesday, 30 May 2023 at 04:15:22 UTC, Ali Çehreli wrote:

On 5/29/23 19:57, Cecil Ward wrote:

> I wish to have one routine
> that can be called with either immutable or (possibly)
mutable argument
> values.

'const' should take both immutable and mutable. Can you show 
your case with a short example?


> Could I make the one routine into a template?

That could work but give 'in' parameters a try:

  https://dlang.org/spec/function.html#in-params

Ali


T2 foo( in T1 x ) { return bar( x ) };

It was with something vaguely like the above that I had to remove 
the in (templatised generic function possibly) in order to get it 
to compile with GDC or LDC on godbolt.org (or d.godbolt.org) 
latest versions available. -O3 -release/-frelease 
-march=native/-mcpu-native





Re: Code duplication where you wish to have a routine called with either immutable or mutable arguments

2023-05-30 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/29/23 10:57 PM, Cecil Ward wrote:
I have often come into difficulties where I wish to have one routine 
that can be called with either immutable or (possibly) mutable argument 
values. The argument(s) in question are in, readonly, passed by value or 
passed by const reference. Anyway, no one is trying to write to the 
items passed in as args, no badness attempted.


In cases where const doesn't suffice, inout might. inout has a feature 
that it can be used in cases where a const nested behind multiple 
references would not work.


-Steve


Re: Code duplication where you wish to have a routine called with either immutable or mutable arguments

2023-05-29 Thread Ali Çehreli via Digitalmars-d-learn

On 5/29/23 19:57, Cecil Ward wrote:

> I wish to have one routine
> that can be called with either immutable or (possibly) mutable argument
> values.

'const' should take both immutable and mutable. Can you show your case 
with a short example?


> Could I make the one routine into a template?

That could work but give 'in' parameters a try:

  https://dlang.org/spec/function.html#in-params

Ali



Re: Code duplication where you wish to have a routine called with either immutable or mutable arguments

2023-05-29 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 30 May 2023 at 02:57:52 UTC, Cecil Ward wrote:
I have often come into difficulties where I wish to have one 
routine that can be called with either immutable or (possibly) 
mutable argument values. The argument(s) in question are in, 
readonly, passed by value or passed by const reference. Anyway, 
no one is trying to write to the items passed in as args, no 
badness attempted.


When I call the routine from one place with an argument that is 
immutable and then from another that is not, or it could be 
const as well, or not, that’s when I get all kinds of type 
mismatch errors. And I certainly don’t want to pour cast-like 
type conversion operations over all the place at these problem 
occurrences. it’s surely asking for problems.


Normally you would use const for this, since a const parameter 
can accept either a mutable or an immutable argument. If const 
isn't working for you, then there's probably something else going 
on that you haven't mentioned. Can you post an example of the 
kind of code that gives you these errors?


Code duplication where you wish to have a routine called with either immutable or mutable arguments

2023-05-29 Thread Cecil Ward via Digitalmars-d-learn
I have often come into difficulties where I wish to have one 
routine that can be called with either immutable or (possibly) 
mutable argument values. The argument(s) in question are in, 
readonly, passed by value or passed by const reference. Anyway, 
no one is trying to write to the items passed in as args, no 
badness attempted.


When I call the routine from one place with an argument that is 
immutable and then from another that is not, or it could be const 
as well, or not, that’s when I get all kinds of type mismatch 
errors. And I certainly don’t want to pour cast-like type 
conversion operations over all the place at these problem 
occurrences. it’s surely asking for problems.


Could I make the one routine into a template? Even if I did, that 
would perhaps create additionally problems, since even if it all 
worked and instantiated either immutable or mutable forms of the 
routine, what happens if I have two args and they have a mixture 
of immutable and no immutable args ? So nargs * 2 ( or more) 
possibilities?


I’m out of my depth here.


Re: Transform static immutable string array to tuple.

2023-02-19 Thread realhet via Digitalmars-d-learn

Awesome, Thank both of you!

```
enum a = ["A", "B"];
writeln(a);
writeln(aliasSeqOf!a);
writeln([aliasSeqOf!a]);
```


Re: Transform static immutable string array to tuple.

2023-02-19 Thread H. S. Teoh via Digitalmars-d-learn
On Sun, Feb 19, 2023 at 11:08:34AM +, realhet via Digitalmars-d-learn wrote:
> Hello,
> 
> Is there a better way to transform a string array to a tuple or to an
> AliasSeq?
> 
> ```
> mixin(customSyntaxPrefixes.format!`tuple(%(%s,%))`)
> ```
> 
> I'd like to use this as variable length arguments passed to the
> startsWith() std function (as multiple needles).

In situations like this it's often better to define your dats as an
AliasSeq to begin with, since it's easier to covert that to an array
than the other way round.


T

-- 
I don't trust computers, I've spent too long programming to think that they can 
get anything right. -- James Miller


Re: Transform static immutable string array to tuple.

2023-02-19 Thread ag0aep6g via Digitalmars-d-learn

On Sunday, 19 February 2023 at 11:08:34 UTC, realhet wrote:
Is there a better way to transform a string array to a tuple or 
to an AliasSeq?


```
mixin(customSyntaxPrefixes.format!`tuple(%(%s,%))`)
```


https://dlang.org/phobos/std_meta.html#aliasSeqOf


Transform static immutable string array to tuple.

2023-02-19 Thread realhet via Digitalmars-d-learn

Hello,

Is there a better way to transform a string array to a tuple or 
to an AliasSeq?


```
mixin(customSyntaxPrefixes.format!`tuple(%(%s,%))`)
```

I'd like to use this as variable length arguments passed to the 
startsWith() std function (as multiple needles).




Re: Error: cannot use non-constant CTFE pointer in an initializer `cast(immutable(char)*)TEST`

2022-06-11 Thread Tejas via Digitalmars-d-learn

On Saturday, 11 June 2022 at 11:51:43 UTC, Tejas wrote:

On Saturday, 11 June 2022 at 10:07:46 UTC, test123 wrote:

how to work this around.

```d
__gshared const TEST = import(`onlineapp.d`);
extern(C) void main(){
__gshared  bin_ptr = TEST.ptr;
}
```

```sh
dmd2 -betterC -J. onlineapp.d
onlineapp.d(3): Error: cannot use non-constant CTFE pointer in 
an initializer `cast(immutable(char)*)TEST`


```


Maybe try putting `__gshared  bin_ptr = TEST.ptr;` inside a 
`shared static this(){}`?


I mean, write it like:
```d
__gshared  bin_ptr;
shared static this()
{
bin_ptr = TEST.ptr;
}

__gshared const TEST = import(`onlineapp.d`);


extern(C) void main()
{
}
```

But `bin_ptr` becomes a global in this case :(


Oh wait, `-betterC` is being used ;(

hmm...

Use 
[pragma(crt_constructor)](https://dlang.org/spec/pragma.html#crtctor) instead


```d
__gshared immutable(char)* bin_ptr;

pragma(crt_constructor)
void init_ptr()
{
bin_ptr = TEST.ptr;
}

__gshared TEST = import("this.d");

extern(C) void main()
{
}
```

```sh
(base) [tejasgarhewal@fedora D]$ ldc2 -J. -betterC this.d
(base) [tejasgarhewal@fedora D]$ ./this
```



Re: Error: cannot use non-constant CTFE pointer in an initializer `cast(immutable(char)*)TEST`

2022-06-11 Thread Tejas via Digitalmars-d-learn

On Saturday, 11 June 2022 at 10:07:46 UTC, test123 wrote:

how to work this around.

```d
__gshared const TEST = import(`onlineapp.d`);
extern(C) void main(){
__gshared  bin_ptr = TEST.ptr;
}
```

```sh
dmd2 -betterC -J. onlineapp.d
onlineapp.d(3): Error: cannot use non-constant CTFE pointer in 
an initializer `cast(immutable(char)*)TEST`


```


Maybe try putting `__gshared  bin_ptr = TEST.ptr;` inside a 
`shared static this(){}`?


I mean, write it like:
```d
__gshared  bin_ptr;
shared static this()
{
bin_ptr = TEST.ptr;
}

__gshared const TEST = import(`onlineapp.d`);


extern(C) void main()
{
}
```

But `bin_ptr` becomes a global in this case :(


Error: cannot use non-constant CTFE pointer in an initializer `cast(immutable(char)*)TEST`

2022-06-11 Thread test123 via Digitalmars-d-learn

how to work this around.

```d
__gshared const TEST = import(`onlineapp.d`);
extern(C) void main(){
__gshared  bin_ptr = TEST.ptr;
}
```

```sh
dmd2 -betterC -J. onlineapp.d
onlineapp.d(3): Error: cannot use non-constant CTFE pointer in an 
initializer `cast(immutable(char)*)TEST`


```


Re: Why do immutable variables need reference counting?

2022-04-18 Thread H. S. Teoh via Digitalmars-d-learn
On Mon, Apr 18, 2022 at 12:55:26PM +, wjoe via Digitalmars-d-learn wrote:
> On Sunday, 17 April 2022 at 14:14:37 UTC, H. S. Teoh wrote:
> > Not entirely true. See paragraph 3 in:
> > 
> > https://dlang.org/spec/unittest.html
> > 
> > and 10.24.11.3 in:
> > 
> > https://dlang.org/spec/expression.html#assert_expressions
[...]
> Thanks. Either I missed that the last time I checked or it wasn't
> there ;)
> But the interesting question is: does the compiler go out of its way
> to make that happen or is it just paragraphs written in the spec?

My guess: the spec was amended after the fact. :-D


T

-- 
Those who don't understand D are condemned to reinvent it, poorly. -- Daniel N


Re: Why do immutable variables need reference counting?

2022-04-18 Thread wjoe via Digitalmars-d-learn

On Sunday, 17 April 2022 at 14:14:37 UTC, H. S. Teoh wrote:

Not entirely true. See paragraph 3 in:

https://dlang.org/spec/unittest.html

and 10.24.11.3 in:

https://dlang.org/spec/expression.html#assert_expressions


T


Thanks. Either I missed that the last time I checked or it wasn't 
there ;)
But the interesting question is: does the compiler go out of its 
way to make that happen or is it just paragraphs written in the 
spec?




Re: Why do immutable variables need reference counting?

2022-04-17 Thread ag0aep6g via Digitalmars-d-learn

On 17.04.22 15:27, H. S. Teoh wrote:

On Sun, Apr 17, 2022 at 01:06:36PM +, wjoe via Digitalmars-d-learn wrote:
[...]

On the matter of undefined behavior. Technically a program is in
undefined behavior land after throwing an error, thus every unittest
that continues after assertThrown is therefore nonsense code, is it
not ?


The spec explicitly makes an exception(!) in this case. See 10.24.11.3:

https://dlang.org/spec/expression.html#assert_expressions

as well as 27.3:

https://dlang.org/spec/unittest.html


But the failing assert is not part of the unittest directly. It's in a 
function that is called from the unittest. It takes a generous 
interpretation of the spec to include such asserts in the exception.


Letting failing asserts cause UB is a mistake anyway. It stems from a 
misguided desire to re-use asserts for optimization, when nobody 
actually uses them that way.


Re: Why do immutable variables need reference counting?

2022-04-17 Thread H. S. Teoh via Digitalmars-d-learn
On Sun, Apr 17, 2022 at 04:09:12PM +0200, ag0aep6g via Digitalmars-d-learn 
wrote:
[...]
> Failing asserts are a messy part of the language. They are supposed to
> be:
> 
> 1) not catchable, because they indicate a bug in the program;
> 2) catchable in order to be testable;
> 3) assumed impossible for optimization purposes.
> 
> Those goals are at odds with each other, and I don't think the spec
> manages to consolidate them.

Not entirely true. See paragraph 3 in:

https://dlang.org/spec/unittest.html

and 10.24.11.3 in:

https://dlang.org/spec/expression.html#assert_expressions


T

-- 
Latin's a dead language, as dead as can be; it killed off all the
Romans, and now it's killing me! -- Schoolboy


Re: Why do immutable variables need reference counting?

2022-04-17 Thread ag0aep6g via Digitalmars-d-learn

On 17.04.22 15:06, wjoe wrote:
On the matter of undefined behavior. Technically a program is in 
undefined behavior land after throwing an error, thus every unittest 
that continues after assertThrown is therefore nonsense code, is it not ?


Yes.

Failing asserts are a messy part of the language. They are supposed to be:

1) not catchable, because they indicate a bug in the program;
2) catchable in order to be testable;
3) assumed impossible for optimization purposes.

Those goals are at odds with each other, and I don't think the spec 
manages to consolidate them.


But mutating `immutable` data is not messy. It's simply not allowed.


Re: Why do immutable variables need reference counting?

2022-04-17 Thread H. S. Teoh via Digitalmars-d-learn
On Sun, Apr 17, 2022 at 01:06:36PM +, wjoe via Digitalmars-d-learn wrote:
[...]
> On the matter of undefined behavior. Technically a program is in
> undefined behavior land after throwing an error, thus every unittest
> that continues after assertThrown is therefore nonsense code, is it
> not ?

The spec explicitly makes an exception(!) in this case. See 10.24.11.3:

https://dlang.org/spec/expression.html#assert_expressions

as well as 27.3:

https://dlang.org/spec/unittest.html


T

-- 
An elephant: A mouse built to government specifications. -- Robert Heinlein


Re: Why do immutable variables need reference counting?

2022-04-17 Thread wjoe via Digitalmars-d-learn

On Thursday, 14 April 2022 at 12:10:04 UTC, ag0aep6g wrote:

On 14.04.22 13:42, wjoe wrote:
Undefined behavior yes, but regardless the example proves it 
can be done in @system code.
A few versions ago, possibly due to a bug or regression, the 
compiler didn't complain in @safe code either.


Of course you are correct academically. However, since it's 
possible, I'd wager my last hat that code like this is out in 
the wild.


No, it cannot be done in @system code. The example only proves 
that you can write nonsense code that has no defined meaning.


Note that the nonsense you wrote behaves as you describe only 
in Windows. Elsewhere, you get a segfault.


But it doesn't matter how the executable actually behaves. You 
cannot cite the result of undefined behavior when arguing 
language semantics.


Well I'm not using Windows so I wouldn't know but I compiled an 
ran that program on Linux and it didn't segfault. If it had I 
wouldn't have included that part in my reply.


On the matter of undefined behavior. Technically a program is in 
undefined behavior land after throwing an error, thus every 
unittest that continues after assertThrown is therefore nonsense 
code, is it not ?


Re: Why do immutable variables need reference counting?

2022-04-14 Thread ag0aep6g via Digitalmars-d-learn

On 14.04.22 13:42, wjoe wrote:
Undefined behavior yes, but regardless the example proves it can be done 
in @system code.
A few versions ago, possibly due to a bug or regression, the compiler 
didn't complain in @safe code either.


Of course you are correct academically. However, since it's possible, 
I'd wager my last hat that code like this is out in the wild.


No, it cannot be done in @system code. The example only proves that you 
can write nonsense code that has no defined meaning.


Note that the nonsense you wrote behaves as you describe only in 
Windows. Elsewhere, you get a segfault.


But it doesn't matter how the executable actually behaves. You cannot 
cite the result of undefined behavior when arguing language semantics.


Re: Why do immutable variables need reference counting?

2022-04-14 Thread wjoe via Digitalmars-d-learn

On Tuesday, 12 April 2022 at 23:23:59 UTC, Ali Çehreli wrote:

[...]


Looking at this from a technical perspective - everything you say 
is true - and thanks for clearing up some of my confusion in that 
department.


Looking at this from a natural language (English) perspective - 
words prompt ideas and expectations. If these expectations aren't 
met confusion and misunderstanding happens (and that's not just 
true for software development).
Although, perhaps, that's only a problem for (some) non native 
English speakers ? The fact remains that there's confusion and 
misunderstandings regarding const, immutable and const 2.




Re: Why do immutable variables need reference counting?

2022-04-14 Thread wjoe via Digitalmars-d-learn

On Tuesday, 12 April 2022 at 22:23:18 UTC, ag0aep6g wrote:

On Tuesday, 12 April 2022 at 19:54:13 UTC, wjoe wrote:
Especially since it's only a promise and the compiler accepts 
this:


void foo (const(char)[] arr)
{
  cast(char[])arr[0..3] = "baz";
}
string bar = "123";
foo(bar);
assert(bar=="baz");

But I could cast away const and modify the string bar.


No, you could not. You're relying on undefined behavior there. 
Just because the compiler accepts something, doesn't mean it's 
ok.


If you want to be guarded against wandering into undefined 
territory, that's what @safe does. With @safe, the cast doesn't 
compile.


Undefined behavior yes, but regardless the example proves it can 
be done in @system code.
A few versions ago, possibly due to a bug or regression, the 
compiler didn't complain in @safe code either.


Of course you are correct academically. However, since it's 
possible, I'd wager my last hat that code like this is out in the 
wild.


Re: Why do immutable variables need reference counting?

2022-04-13 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, Apr 13, 2022 at 08:39:17AM -0700, Ali Çehreli via Digitalmars-d-learn 
wrote:
> On 4/12/22 21:34, Salih Dincer wrote:
> 
> > I tried the following and I didn't understand one thing: Why is
> > there no need to use dup when slicing?
[...]

Because of two things: (1) there is a GC, and (2) characters in a string
are immutable.

Without (1), you will end up with either a memory leak or a dangling
pointer; without (2), your slice may randomly mutate when you don't
expect it to.


T

-- 
May you live all the days of your life. -- Jonathan Swift


Re: Why do immutable variables need reference counting?

2022-04-13 Thread Ali Çehreli via Digitalmars-d-learn

On 4/12/22 21:34, Salih Dincer wrote:

> I tried the following and I didn't understand one thing: Why is there no
> need to use dup when slicing?

I don't think I understand you fully.

> ```d
> struct S(T) {
>   T fileName;
>
>this(T fileName) {
>  this.fileName = fileName;
>  report();
>}
>
>~this() { report(); }
>
>void report(string func = __FUNCTION__) {
>  import std.stdio;
>  writefln!"%s\nworking with %s"(func, fileName);
>}
> }
> alias T1 = const(char)[];
> alias T2 = const char[];
> alias T3 = const(char[]); // T3 == T2
> alias T4 = immutable char[]; // Not compiling!
>
>
> void main() {
>auto fileName = "foo.txt".dup;

In every test case that 'fileName' is char[].

>auto s = S!T1(fileName);
>fileName[0..3] = "bar";

For that reason, that expression will always succeed. And that's the 
point I tried to make: Without immutable, struct S *must* make a copy in 
order to guarantee that its member will remain the same.


> }/* Results:

[...]

>*
>*T4
>*
>Error: slice `fileName[0..3]` is not mutable

Your code was different because I get an error that I expect: The 
following line fails.


  auto s = S!T4(fileName);

cannot pass argument `fileName` of type `char[]` to parameter 
`immutable(string) fileName`


Exactly! struct S wants immutable (to guarantee that nobody will mutate 
it) but 'fileName' in main is not immutable. You can make it pass in the 
T4 case


a) by making an immutable copy with .idup:

  auto s = S!T4(fileName.idup);

b) by converting 'fileName' to immutable without a copy:

  import std.exception;
  auto s = S!T4(fileName.assumeUnique);
  // But then, the following will fail. Awesome!
  // fileName[0..3] = "bar";

I am amazed everyday how great D is; such a fun engineering tool!

Ali



Re: Why do immutable variables need reference counting?

2022-04-12 Thread Salih Dincer via Digitalmars-d-learn

On Monday, 11 April 2022 at 21:48:56 UTC, Ali Çehreli wrote:

On 4/11/22 08:02, Paul Backus wrote:

> any pointers or references

To add, Salih and I were in an earlier discussion where that 
concept appeared as "indirections."


Ali


I tried the following and I didn't understand one thing: Why is 
there no need to use dup when slicing?


```d
struct S(T) {
 T fileName;

  this(T fileName) {
this.fileName = fileName;
report();
  }

  ~this() { report(); }

  void report(string func = __FUNCTION__) {
import std.stdio;
writefln!"%s\nworking with %s"(func, fileName);
  }
}
alias T1 = const(char)[];
alias T2 = const char[];
alias T3 = const(char[]); // T3 == T2
alias T4 = immutable char[]; // Not compiling!


void main() {
  auto fileName = "foo.txt".dup;
  auto s = S!T1(fileName);
  fileName[0..3] = "bar";
}/* Results:
  *
  *T1:
  *
  source.S!(const(char)[]).S.this
  working with foo.txt.
  source.S!(const(char)[]).S.~this
  working with bar.txt.
  *
  *T2:
  *
  source.S!(const(char[])).S.this
  working with foo.txt
  source.S!(const(char[])).S.~this
  working with bar.txt
  *
  *T3:
  *
  source.S!(const(char[])).S.this
  working with foo.txt
  source.S!(const(char[])).S.~this
  working with bar.txt
  *
  *T4
  *
  Error: slice `fileName[0..3]` is not mutable
  */
```

SDB@79


Re: Why do immutable variables need reference counting?

2022-04-12 Thread Ali Çehreli via Digitalmars-d-learn

On 4/12/22 12:54, wjoe wrote:

> I.e. immutable is constant data which is created at compile time - like
> laws of physics,

For completeness, we already have 'enum' and 'static const' for that.

> should get a better name - maybe 'in' and get rid of const.

Yes! 'in' for parameters! :D

>> import std.stdio;
>> import std.format;
>>
>> struct S {
>>   const(char)[] fileName;
>>
>>   this(const(char)[] fileName) {
>> this.fileName = fileName;
>> report();
>>   }
>>
>>   ~this() {
>> report();
>>   }
>>
>>   void report(string func = __FUNCTION__) {
>> writefln!"%s working with %s."(func, fileName);
>>   }
>> }
>>
>> void main() {
>>   char[] fileName = "foo.txt".dup;
>>   auto s = S(fileName);
>>   fileName[0..3] = "bar";
>> }
>>
>>
>> If fileName were immutable, then the owner would not be able to mutate
>> anyway, so the struct could get away without copying the file name.
>>
>> Ali
>
> I presume you refer to fileName in main() ?

No, I meant the member 'fileName'. If the member is 'const' (as in C++ 
and as in the example above), you have to take a copy because the caller 
may mutate. (The example is demonstrating the case where the struct 
assumes data won't changed and gets surprised by the mutation.)


> And if yes, if it were
> const, it couldn't be mutated either,

You started as assuming 'fileName' in main, so, I will continue with 
that. If the struct had 'const fileName' and pleaded that the caller 
also define a 'const' variable, that would be wishful thinking. The 
struct cannot trust that all callers will obey that plea.


That kind of trust (more like guarantee) comes with 'immutable' and this 
is a good example of how immutable is different from const. (immutable 
does not exist in some languages like C++.)


> so isn't immutable and const sort
> of synonymous in that case or am I missing your point?

If on the other hand, the member were immutable, the caller would have 
to provide immutable data and the struct could rely on the fact that the 
data was immutable forever. No need for a copy...


Ali



Re: Why do immutable variables need reference counting?

2022-04-12 Thread ag0aep6g via Digitalmars-d-learn

On Tuesday, 12 April 2022 at 19:54:13 UTC, wjoe wrote:
Especially since it's only a promise and the compiler accepts 
this:


void foo (const(char)[] arr)
{
  cast(char[])arr[0..3] = "baz";
}
string bar = "123";
foo(bar);
assert(bar=="baz");

But I could cast away const and modify the string bar.


No, you could not. You're relying on undefined behavior there. 
Just because the compiler accepts something, doesn't mean it's ok.


If you want to be guarded against wandering into undefined 
territory, that's what @safe does. With @safe, the cast doesn't 
compile.


Re: Why do immutable variables need reference counting?

2022-04-12 Thread wjoe via Digitalmars-d-learn

On Monday, 11 April 2022 at 22:10:07 UTC, Ali Çehreli wrote:

On 4/11/22 05:57, wjoe wrote:

> And because the data could be
> in ROM any modification is an error.

Fully agreed. However, how could I initialize such an object 
then? (You may have meant a read-only memory page instead of 
ROM.)




I was thinking during compile time. By initializing a variable 
with immutable data or a pointer that points to an address e.G. 
an EEPROM.


Even 'const' cause confusions because it's used in at least two 
different ways (even e.g. in C++):


1) I will not mutate data through this reference. For example, 
a parameter that is pointer to const achieves that:


  void foo (const(int)[] arr);

2) This variable is const:

  const i = 42;

Well, there is the confusion: There is no "reference" in the 
second case at all!


In general, I guess, it's a bad idea to reuse the same word for 2 
or more distinctly different ideas. Maybe the const keyword in 1) 
should have a better name. Especially since it's only a promise 
and the compiler accepts this:


void foo (const(char)[] arr)
{
  cast(char[])arr[0..3] = "baz";
}
string bar = "123";
foo(bar);
assert(bar=="baz");

But I could cast away const and modify the string bar.

So with that said
I don't agree with you when you say immutability should be 
const's domain because const covers item 1 above as well, where 
there is no immutability of data whatsoever. The data may be 
perfectly mutable or immutable, where my access will be 
readonly.


When I said immutability should be the domain of const I am 
referring only to 2).


I.e. immutable is constant data which is created at compile time 
- like laws of physics,
const as in 2) is constant data which is created at run time - 
like man made laws,

and 1) should get a better name - maybe 'in' and get rid of const.

And to be able to use immutable anywhere other than where 
immutable is explicitly specified, a copy is necessary.


I know it's not as simple as that. But one can dream, right? :)


producer from mutating it further. Example:

import std.stdio;
import std.format;

struct S {
  const(char)[] fileName;

  this(const(char)[] fileName) {
this.fileName = fileName;
report();
  }

  ~this() {
report();
  }

  void report(string func = __FUNCTION__) {
writefln!"%s working with %s."(func, fileName);
  }
}

void main() {
  char[] fileName = "foo.txt".dup;
  auto s = S(fileName);
  fileName[0..3] = "bar";
}


If fileName were immutable, then the owner would not be able to 
mutate anyway, so the struct could get away without copying the 
file name.


Ali


I presume you refer to fileName in main() ? And if yes, if it 
were const, it couldn't be mutated either, so isn't immutable and 
const sort of synonymous in that case or am I missing your point?


Re: Why do immutable variables need reference counting?

2022-04-12 Thread Ali Çehreli via Digitalmars-d-learn

On 4/12/22 03:28, Dom DiSc wrote:
> On Monday, 11 April 2022 at 22:10:07 UTC, Ali Çehreli wrote:
>> 1) I will not mutate data through this reference. For example, a
>> parameter that is pointer to const achieves that:
>>
>>   void foo (const(int)[] arr);
>>
>> 2) This variable is const:
>>
>>   const i = 42;
>>
>> Well, there is the confusion: There is no "reference" in the second
>> case at all!
> I think this second case should not be allowed. Use
>
> immutable i = 42;
>
> instead. The meaning is identical,

Only if there are no indirections as in 'int'. If I use a struct

struct S {
  const(char[]) arr;
}

void foo(const(char[]) arr) {
  immutable s = immutable(S)(arr);  // <-- ERROR:
  // Error: cannot implicitly convert expression `arr` of type 
`const(char[])` to `immutable(string)`

}

void main() {
  int[] arr;
  foo(arr);
}

The reason is a property of immutable that I like to describe as 
"selective" (or "demanding"). The struct variable cannot be immutable 
because it would be demanding that its constructor argument be 
immutable, which cannot be because foo's 'const' parameter hides that 
information even when it were immutable e.g. in main().


> but we could remove the burden of two
> different meanings from const if it is not allowed. const should only be
> allowed in function declarations. A variable must be declared either
> mutable or immutable. It's only functions that may guarantee not to
> modify a parameter or the objects they belong to, and so are allowed to
> work on both mutable and immutable objects.

I understand but the guarantee of immutable seems to leave no other choice.

Ali



Re: Why do immutable variables need reference counting?

2022-04-12 Thread Dom DiSc via Digitalmars-d-learn

On Monday, 11 April 2022 at 22:10:07 UTC, Ali Çehreli wrote:
1) I will not mutate data through this reference. For example, 
a parameter that is pointer to const achieves that:


  void foo (const(int)[] arr);

2) This variable is const:

  const i = 42;

Well, there is the confusion: There is no "reference" in the 
second case at all!

I think this second case should not be allowed. Use

   immutable i = 42;

instead. The meaning is identical, but we could remove the burden 
of two different meanings from const if it is not allowed. const 
should only be allowed in function declarations. A variable must 
be declared either mutable or immutable. It's only functions that 
may guarantee not to modify a parameter or the objects they 
belong to, and so are allowed to work on both mutable and 
immutable objects.




Re: Why do immutable variables need reference counting?

2022-04-11 Thread Ali Çehreli via Digitalmars-d-learn

On 4/11/22 05:57, wjoe wrote:

> To my understanding immutable data should reside in a separate data
> segment which itself could reside in ROM.

We are getting into implementation details which a programming language 
acts as not to care (but has to do especially when it's a system 
programming language like D. :) ).


> So when the variable, or 'pointer' to the data, goes out of scope just
> the 'pointer' is gone, the actual data unreachable, but still there.

I think it translates to the destructor never being executed. Otherwise, 
nobody would even know whether the memory location is reused for other 
pursposes later on.


> Due to its immutable nature immutable data can't be changed and this, to
> my understanding, includes deallocation.

D one language where object lifetime is deliberately separate from 
memory allocation.


> And because the data could be
> in ROM any modification is an error.

Fully agreed. However, how could I initialize such an object then? (You 
may have meant a read-only memory page instead of ROM.)


> immutable data on the fly doesn't make sense to me - that should be
> const's domain.

Even 'const' cause confusions because it's used in at least two 
different ways (even e.g. in C++):


1) I will not mutate data through this reference. For example, a 
parameter that is pointer to const achieves that:


  void foo (const(int)[] arr);

2) This variable is const:

  const i = 42;

Well, there is the confusion: There is no "reference" in the second case 
at all!


I don't agree with you when you say immutability should be const's 
domain because const covers item 1 above as well, where there is no 
immutability of data whatsoever. The data may be perfectly mutable or 
immutable, where my access will be readonly.


Perhaps you are saying the same thing but enters D's immutable: The data 
is immutable.


immutable data on the fly can be very useful because e.g. it makes 
multithreaded programming trivial in some cases by removing the need for 
locking.


> Strings, I know. But the way things are, I hardly see a
> difference between immutable and const.

Imagine a File struct that holds on to a file name. In C++, we would 
have to make a copy of the constructor argument for two reasons:


1) Lifetime of the object might be short. This is not a problem in D 
because of the GC.


2) The data might change after I start holding on to it through a 
reference. This is not a problem *only if* data were immutable because 
my const parameter cannot preclude the producer from mutating it 
further. Example:


import std.stdio;
import std.format;

struct S {
  const(char)[] fileName;

  this(const(char)[] fileName) {
this.fileName = fileName;
report();
  }

  ~this() {
report();
  }

  void report(string func = __FUNCTION__) {
writefln!"%s working with %s."(func, fileName);
  }
}

void main() {
  char[] fileName = "foo.txt".dup;
  auto s = S(fileName);
  fileName[0..3] = "bar";
}

The output shows that the file name changed between construction and 
destruction:


deneme.S.this working with foo.txt.
deneme.S.~this working with bar.txt.

If fileName were immutable, then the owner would not be able to mutate 
anyway, so the struct could get away without copying the file name.


Ali



Re: Why do immutable variables need reference counting?

2022-04-11 Thread Ali Çehreli via Digitalmars-d-learn

On 4/11/22 08:02, Paul Backus wrote:

> any pointers or references

To add, Salih and I were in an earlier discussion where that concept 
appeared as "indirections."


Ali



Re: Why do immutable variables need reference counting?

2022-04-11 Thread Paul Backus via Digitalmars-d-learn

On Monday, 11 April 2022 at 12:12:39 UTC, Salih Dincer wrote:

It worked for me in a different way.


1 is (about to be) alive!

2 is (already) dead.
2 is (already) dead.
2 is (already) dead.


2 is (already) dead.

2 is (already) dead.
Hello D!
1 is (already) dead.

Because I changed the code like this.

```d

struct S
{
  . . .

  string toString() { return ""; }
}

//S test(inout S s)/*
S test(S s)//*/
{
  s.i = 2;
  return s;
}

void main()
{
  immutable s = S(1);
  test(s).writeln;
  "Hello".writefln!"%s D!";
}
```

If the inout is set, it does not allow compilation.


Because `S` does not contain any pointers or references, you are 
allowed to create a mutable *copy* of an `S` from an `immutable` 
source. That's what happens when you pass it to `test`.


The extra destructor calls come from the copies made by `test` 
and `writeln`. If you add a copy constructor, you can see this 
happening in the output:


```d
struct S {

/* ... */

this(ref inout typeof(this) other) inout {
this.i = other.i;
writeln(i, " was copied.");
}
}
```

```
1 is (about to be) alive!
1 was copied.
2 was copied.
2 is (already) dead.
2 was copied.
2 was copied.
2 was copied.
2 is (already) dead.
2 is (already) dead.

2 is (already) dead.
2 is (already) dead.
Hello D!
1 is (already) dead.
```

1 constructor call + 5 copies = 6 destructor calls.


Re: Why do immutable variables need reference counting?

2022-04-11 Thread wjoe via Digitalmars-d-learn

On Monday, 11 April 2022 at 03:24:11 UTC, Ali Çehreli wrote:

On 4/10/22 20:05, norm wrote:
> On Sunday, 10 April 2022 at 23:19:47 UTC, rikki cattermole
wrote:

> In my mind immutable data
> means the data will not change and neither will the result of
reading
> that data, ever.

Yes.

> I don't get how you can have thread safety guarantees based
on immutable
> if reading that data in a thread suddenly becomes undefined
behaviour
> and could return anything.

Yes, it would be a bug to attempt to read data that is not live 
anymore.


> That isn't immutable then.

The lifetime of immutable data can start and end.

import std.stdio;

struct S {
  int i;

  this(int i) {
this.i = i;
writeln(i, " is (about to be) alive!");
  }

  ~this() {
writeln(i, " is (already) dead.");
  }
}

void main() {
  foreach (i; 0 .. 3) {
immutable s = S(i);
  }
}

The output:

0 is (about to be) alive!
0 is (already) dead.
1 is (about to be) alive!
1 is (already) dead.
2 is (about to be) alive!
2 is (already) dead.

Module-level immutable and 'static const' would live much 
longer but they have a lifetime as well. However, today, the 
destructor cannot be executed on an immutable object, so I 
remove the qualifiers with cast(), which sohuld be undefined 
behavior (today?).


immutable(S) moduleS;

shared static this() {
  moduleS = S(42);
}

shared static ~this() {
  destroy(cast()moduleS);
}

void main() {
}

> Once instantiated
> immutable data persists for the remainder of the program.

That seems to be the misunderstanding. Again, I think 
module-level 'immutable' and 'static const' data fits that 
description.


> You may not
> have access if the variable goes out of scope, but if you do
it will
> always be there and always return the same value when you
read from memory.

That description fits D's GC-owned data (including immutables). 
The lifetime ends when there is no reference to it.


Another example is immutable messages passed between threads 
with std.concurrency: That kind of data clearly originates at 
run time and the receiving end keeps the data alive as long as 
it needs.


Ali


To my understanding immutable data should reside in a separate 
data segment which itself could reside in ROM.
So when the variable, or 'pointer' to the data, goes out of scope 
just the 'pointer' is gone, the actual data unreachable, but 
still there.
Due to its immutable nature immutable data can't be changed and 
this, to my understanding, includes deallocation. And because the 
data could be in ROM any modification is an error. How would you 
deallocate ROM anyways?
Your foreach could be unrolled at compile time, however it could 
easily be changed to a runtime only loop but this entire concept 
of creating immutable data on the fly doesn't make sense to me - 
that should be const's domain. Strings, I know. But the way 
things are, I hardly see a difference between immutable and const.


Re: Why do immutable variables need reference counting?

2022-04-11 Thread Salih Dincer via Digitalmars-d-learn

On Monday, 11 April 2022 at 03:24:11 UTC, Ali Çehreli wrote:


The output:

0 is (about to be) alive!
0 is (already) dead.
1 is (about to be) alive!
1 is (already) dead.
2 is (about to be) alive!
2 is (already) dead.


It worked for me in a different way.


1 is (about to be) alive!

2 is (already) dead.
2 is (already) dead.
2 is (already) dead.


2 is (already) dead.

2 is (already) dead.
Hello D!
1 is (already) dead.

Because I changed the code like this.

```d

struct S
{
  . . .

  string toString() { return ""; }
}

//S test(inout S s)/*
S test(S s)//*/
{
  s.i = 2;
  return s;
}

void main()
{
  immutable s = S(1);
  test(s).writeln;
  "Hello".writefln!"%s D!";
}
```

If the inout is set, it does not allow compilation.

Thanks, SDB79


Re: Why do immutable variables need reference counting?

2022-04-11 Thread user1234 via Digitalmars-d-learn

On Sunday, 10 April 2022 at 23:05:24 UTC, norm wrote:

Hi All,

I am clearly misunderstanding something fundamental, and 
probably obvious :D


Reading some of the discussions on __metadata I was wondering 
if someone could explain why a immutable reference counting 
type is needed. By definition a reference counter cannot be 
immutable, so what would be the use case that requires it? It 
cannot really be pure nor safe either because the ref goes out 
of scope and the allocation is freed. How is this immutable?



Thanks,
Norm


refcounting would require a concept of "tail const" / "tail 
immutable" so that transitivity of the qualifier does not affect 
the data used to refcount (basically the field that hold the 
count) but only the data that **are** refcounted.


Re: Why do immutable variables need reference counting?

2022-04-11 Thread IGotD- via Digitalmars-d-learn

On Sunday, 10 April 2022 at 23:19:47 UTC, rikki cattermole wrote:


immutable isn't tied to lifetime semantics.

It only says that this memory will never be modified by anyone 
during its lifetime.


Anyway, the real problem is with const. Both mutable and 
immutable become it automatically.


I was thinking about that, often when using const you use it when 
passing parameters to functions. This is essentially borrowing. 
The situation is similar with C++ with unique_ptr and shared_ptr. 
Often C++ interfaces use const* when using pointers and not their 
smart pointer counterparts, so essentially the ownership remains, 
while "borrowing" are using raw pointers. A C++ interface only 
accepts the smart pointers when you want to change ownership. D 
could use a similar approach, when using pointers/references you 
shouldn't alter the internal data including reference count.


What I would interested in is if D could have move by default 
depending on type. In this case the RC pointer wrapper could be 
move by default. Increasing is only done when calling "clone" 
(similar to Rust). This way RC increases are optimized naturally. 
What I don't want from Rust is the runtime aliasing check 
(RefCell) on at all times. I rather go with that the compiler 
assumes no aliasing but the programmer is responsible for this. 
You can have runtime aliasing/borrowing check in debug mode but 
in release build it can be removed. This is similar to bounds 
checking where you can choose to have it or not.


Re: Why do immutable variables need reference counting?

2022-04-10 Thread rikki cattermole via Digitalmars-d-learn
Storage classes like immutable/const/shared are not tied to any memory 
management strategy. Nor does it dictate memory lifetime.


It only dictates how it can be interacted with when you have a reference 
to it.


Re: Why do immutable variables need reference counting?

2022-04-10 Thread Ali Çehreli via Digitalmars-d-learn

On 4/10/22 20:05, norm wrote:
> On Sunday, 10 April 2022 at 23:19:47 UTC, rikki cattermole wrote:

> In my mind immutable data
> means the data will not change and neither will the result of reading
> that data, ever.

Yes.

> I don't get how you can have thread safety guarantees based on immutable
> if reading that data in a thread suddenly becomes undefined behaviour
> and could return anything.

Yes, it would be a bug to attempt to read data that is not live anymore.

> That isn't immutable then.

The lifetime of immutable data can start and end.

import std.stdio;

struct S {
  int i;

  this(int i) {
this.i = i;
writeln(i, " is (about to be) alive!");
  }

  ~this() {
writeln(i, " is (already) dead.");
  }
}

void main() {
  foreach (i; 0 .. 3) {
immutable s = S(i);
  }
}

The output:

0 is (about to be) alive!
0 is (already) dead.
1 is (about to be) alive!
1 is (already) dead.
2 is (about to be) alive!
2 is (already) dead.

Module-level immutable and 'static const' would live much longer but 
they have a lifetime as well. However, today, the destructor cannot be 
executed on an immutable object, so I remove the qualifiers with cast(), 
which sohuld be undefined behavior (today?).


immutable(S) moduleS;

shared static this() {
  moduleS = S(42);
}

shared static ~this() {
  destroy(cast()moduleS);
}

void main() {
}

> Once instantiated
> immutable data persists for the remainder of the program.

That seems to be the misunderstanding. Again, I think module-level 
'immutable' and 'static const' data fits that description.


> You may not
> have access if the variable goes out of scope, but if you do it will
> always be there and always return the same value when you read from 
memory.


That description fits D's GC-owned data (including immutables). The 
lifetime ends when there is no reference to it.


Another example is immutable messages passed between threads with 
std.concurrency: That kind of data clearly originates at run time and 
the receiving end keeps the data alive as long as it needs.


Ali



Re: Why do immutable variables need reference counting?

2022-04-10 Thread norm via Digitalmars-d-learn

On Sunday, 10 April 2022 at 23:19:47 UTC, rikki cattermole wrote:


immutable isn't tied to lifetime semantics.

It only says that this memory will never be modified by anyone 
during its lifetime.


This is clearly where I am misunderstanding. In my mind immutable 
data means the data will not change and neither will the result 
of reading that data, ever.


I don't get how you can have thread safety guarantees based on 
immutable if reading that data in a thread suddenly becomes 
undefined behaviour and could return anything. That isn't 
immutable then. Once instantiated immutable data persists for the 
remainder of the program. You may not have access if the variable 
goes out of scope, but if you do it will always be there and 
always return the same value when you read from memory.


Thanks for replying, I am not trying to be argumentative here, 
just stating what I thought it meant and why I am confused. I'll 
be doing some more reading of the D spec to better understand 
immutability.


Cheers,
Norm




Re: Why do immutable variables need reference counting?

2022-04-10 Thread rikki cattermole via Digitalmars-d-learn



immutable isn't tied to lifetime semantics.

It only says that this memory will never be modified by anyone during 
its lifetime.


Anyway, the real problem is with const. Both mutable and immutable 
become it automatically.


Why do immutable variables need reference counting?

2022-04-10 Thread norm via Digitalmars-d-learn

Hi All,

I am clearly misunderstanding something fundamental, and probably 
obvious :D


Reading some of the discussions on __metadata I was wondering if 
someone could explain why a immutable reference counting type is 
needed. By definition a reference counter cannot be immutable, so 
what would be the use case that requires it? It cannot really be 
pure nor safe either because the ref goes out of scope and the 
allocation is freed. How is this immutable?



Thanks,
Norm



Re: How do you properly use immutable on class members?

2022-03-29 Thread Fruitful Approach via Digitalmars-d-learn

On Tuesday, 29 March 2022 at 18:59:41 UTC, H. S. Teoh wrote:
On Tue, Mar 29, 2022 at 05:58:11PM +, Fruitful Approach via 
Digitalmars-d-learn wrote:

[...]


1) `immutable immutable(Prop)[]` is identical to 
`immutable(Prop[])`.
   Immutable is transitive. There is no need to spell it in 
such a

   verbose way.

[...]


Thank you thank you thank you!  You've more than answered my 
concerns about using them.  So you're saying I should make my 
ctor parameters either const or `in`.  I will code some more and 
see if I can make this hurdle.


Re: How do you properly use immutable on class members?

2022-03-29 Thread Salih Dincer via Digitalmars-d-learn

On Tuesday, 29 March 2022 at 19:26:51 UTC, Ali Çehreli wrote:


Better yet, and as I know you know :), and as it comes up 
occasionally but I usually forget in my own code; 'in' is much 
better than 'const' on function parameters because it has super 
powers when compiled with -preview=in:




Hello to everyone.

I think const is a redundant thing. Can you show me a direct 
side-effect that happens when we don't use const?


SDB@79


Re: How do you properly use immutable on class members?

2022-03-29 Thread Ali Çehreli via Digitalmars-d-learn

On 3/29/22 10:58, Fruitful Approach wrote:

> so I end up undoing all the places I inserted it.

That's what I do as well, which proves my 'const' object only hoped to 
be 'const'. I never say "I have to respect my decision from 10 minutes 
ago, so I must keep this object const." Nope! 'const' is replaced with 
'auto' instantly. :)


'const' and 'immutable' on member variables are trouble because they 
make objects unassignable. (But you said 'class', so there is no such 
issue with them in D anyway.) But is that too bad? Is assignment 
overrated anyway? I don't know... :/


Ali



Re: How do you properly use immutable on class members?

2022-03-29 Thread Ali Çehreli via Digitalmars-d-learn

On 3/29/22 11:59, H. S. Teoh wrote:

> As a general principle, const should be used when you're on the
> receiving end of data that should not be changed (e.g., function
> parameters)

Better yet, and as I know you know :), and as it comes up occasionally 
but I usually forget in my own code; 'in' is much better than 'const' on 
function parameters because it has super powers when compiled with 
-preview=in:


  https://dlang.org/spec/function.html#in-params

Ali



Re: How do you properly use immutable on class members?

2022-03-29 Thread H. S. Teoh via Digitalmars-d-learn
On Tue, Mar 29, 2022 at 05:58:11PM +, Fruitful Approach via 
Digitalmars-d-learn wrote:
> I have immutable members:
> 
> `immutable immutable(Prop)[] axioms` which I can't initialize with
> Prop[], so I call this "immutable-poisoning" of the rest of my code.
> Can you provide a 10 line example of how to best work with immutable
> types, specifically immutable members, together with ctor, and
> accessor methods?

1) `immutable immutable(Prop)[]` is identical to `immutable(Prop[])`.
   Immutable is transitive. There is no need to spell it in such a
   verbose way.

2) Immutable fields can be initialized only in the ctor.

3) You *can* initialize immutable data with mutable data if it's a
   unique reference. Usually you get a unique reference by returning it
   from a pure function. For example:

Prop[] makeProps() pure {
return [ Prop.init ];
}

immutable(Prop[]) axioms = makeProps(); // OK

So in your case, what you could do is to initialize your immutable field
in your ctor, like this:

class MyClass {
immutable(Prop[]) axioms;

private Prop[] makeAxioms() pure { ... }

this() {
axioms = makeAxioms();
}
}


[...]
> Every time I use const or immutable in C++ or D I end up failing with
> too many weird compilation errors, so I end up undoing all the places
> I inserted it.  Should I just _not use_ immutable or const except for
> on `const` method decoration where applicable?

D's const/immutable and C++'s const are very different beasts.  D's
const and immutable are transitive, meaning that if your outer reference
is const, then everything it refers to will also be const (we call it
"turtles all the way down").

Also, the way const interacts with mutable/immutable:

     const
 /   \
    (mutable) immutable

Both mutable and immutable implicitly convert to const, but const does
not implicitly convert to mutable/immutable (in general; there are
exceptions like mutable -> immutable when it's a unique reference
returned from a pure function, e.g. above).

Basically, const means "I'm not allowed to change this, but somebody
else might". Immutable means "I'm not allowed to change this, neither is
anybody else."

As a general principle, const should be used when you're on the
receiving end of data that should not be changed (e.g., function
parameters); immutable should be used when you're the owner of data that
should not be change.


T

-- 
Holding a grudge is like drinking poison and hoping the other person dies. -- 
seen on the 'Net


How do you properly use immutable on class members?

2022-03-29 Thread Fruitful Approach via Digitalmars-d-learn

I have immutable members:

`immutable immutable(Prop)[] axioms` which I can't initialize 
with Prop[], so I call this "immutable-poisoning" of the rest of 
my code.  Can you provide a 10 line example of how to best work 
with immutable types, specifically immutable members, together 
with ctor, and accessor methods?


Also do I need to do `immutable immutable(Prop)[]` - that seems 
kind of wordy, especially when I have to duplicate that typing 
elsewhere.  I could use an alias called `Axioms` I guess.


Every time I use const or immutable in C++ or D I end up failing 
with too many weird compilation errors, so I end up undoing all 
the places I inserted it.  Should I just _not use_ immutable or 
const except for on `const` method decoration where applicable?


There's no good tutorial on a realistic immutable example AFAIK.


Re: This is bug or not? (immutable class containing struct with dtor)

2021-12-18 Thread Denis Feklushkin via Digitalmars-d-learn

On Saturday, 18 December 2021 at 12:50:17 UTC, Tejas wrote:


As Ali said, this is an implementation issue.

So I guess the answer to your question is that this is a bug.

Please file a report at [issues.dlang.org](issues.dlang.org)


Looks like this is same case:
https://issues.dlang.org/show_bug.cgi?id=13628



Re: This is bug or not? (immutable class containing struct with dtor)

2021-12-18 Thread Tejas via Digitalmars-d-learn
On Saturday, 18 December 2021 at 11:01:53 UTC, Denis Feklushkin 
wrote:

On Friday, 17 December 2021 at 19:03:05 UTC, Tejas wrote:


Well, I got completely mislead by my experiment 

```d
struct S
{
~this() immutable {}
}
```


Interesting what discussed behaviour isn't affects method what 
implements same functionality as dtor and called explictly at 
each appropriate place.


So for dirty fix I just created

```d
void __custom_dtor() const
{ ... }
```

And then called this __custom_dtor at each dtor what uses this 
struct.


As Ali said, this is an implementation issue.

So I guess the answer to your question is that this is a bug.

Please file a report at [issues.dlang.org](issues.dlang.org)


Re: This is bug or not? (immutable class containing struct with dtor)

2021-12-18 Thread Denis Feklushkin via Digitalmars-d-learn

On Friday, 17 December 2021 at 19:03:05 UTC, Tejas wrote:


Well, I got completely mislead by my experiment 

```d
struct S
{
~this() immutable {}
}
```


Interesting what discussed behaviour isn't affects method what 
implements same functionality as dtor and called explictly at 
each appropriate place.


So for dirty fix I just created

```d
void __custom_dtor() const
{ ... }
```

And then called this __custom_dtor at each dtor what uses this 
struct.


Re: This is bug or not? (immutable class containing struct with dtor)

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

On Friday, 17 December 2021 at 18:51:56 UTC, Ali Çehreli wrote:

On 12/17/21 10:01 AM, Tejas wrote:

> [...]
Storage,

There is no such requirement nor guarantee.

[...]


Well, I got completely mislead by my experiment 

```d
struct S
{
~this() immutable {}
}

void main()
{
    immutable S s = S();
}
```
This failed, so I just came up with reasons to justify this 
behaviour


Thanks for correcting me 


Re: This is bug or not? (immutable class containing struct with dtor)

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

On 12/17/21 10:01 AM, Tejas wrote:

> I think since `immutable` objects are kept in Read Only Storage,

There is no such requirement nor guarantee.

> you
> can't call destructors on them

Destructor is nothing but a piece of code that is executed when an 
object's life ends. A destructor need not touch any member of the object:


struct S {
  ~this() {
import std.stdio;
writeln("done");
  }
}

void main() {
  immutable a = S();
  auto b = immutable(S)();
}

Both objects are immutable there yet their destructor is executed.

> since the objects don't get erased when
> `~this` is called, but rather they get assigned their `.init` value,

That's true only for destroy(), which gets called only if the programmer 
asks for it. Otherwise, destroyed objects don't get assigned any special 
value.


> which tells the GC that they can be collected.

That's not true. The GC collects objects when there are no references to 
them. The values of the object's members have nothing to do with it.


> `immutable class` has nothing to do with it, even the following fails to
> compile:
> ```d
>
>
>
> struct S
> {
>  ~this() immutable {}

That immutable qualifier means "this destructor is for immutable objects 
of this type." However, it seems impossible to define two destructors:


  ~this() {
writeln(__FUNCTION__);
  }

  ~this() immutable {
writeln(__FUNCTION__);
  }

Error: destructor `deneme.S.~this` conflicts with destructor 
`deneme.S.~this` at deneme.d(79)


I think this is an unexplored corner of the language. Part of the 
complication may be due to implementations by an earlier compiler 
contributor, who I heard was responsible for qualifiers on constructors. 
Note two different constructors here:


import std.stdio;

struct S {
  this(int) {
writeln(__PRETTY_FUNCTION__);
  }

  this(int) immutable {
    writeln(__PRETTY_FUNCTION__);
  }
}

void main() {
  auto a = immutable(S)(0);
  auto b = S(1);
}

I bet the problem here is that the implementation in the compiler is 
half-baked on these qualifiers.


Ali



Re: This is bug or not? (immutable class containing struct with dtor)

2021-12-17 Thread Tejas via Digitalmars-d-learn
On Friday, 17 December 2021 at 18:32:43 UTC, Denis Feklushkin 
wrote:

On Friday, 17 December 2021 at 18:02:52 UTC, Tejas wrote:

I improved your sample:

```d
immutable struct S
{
~this() {}
}

immutable struct S2
{
S sss;
~this() {}
}

void main()
{
S2 s = S2();
}
```

```
Error: `immutable` method `serializer_bug.S.~this` is not 
callable using a mutable object
Error: mutable method `serializer_bug.S2.~this` is not callable 
using a `immutable` object
serializer_bug.d(17,5):Consider adding `const` or 
`inout` here

```

immutable dtor can't be called at all?


Nope, seems to go against the very promise it's making

Labelling `~this()` as const or immutable means it won't affect 
the state of the object, but it will, by it's very nature.


That's why I said it's not too much of a stretch to imagine why 
they're disallowed entirely.


Re: This is bug or not? (immutable class containing struct with dtor)

2021-12-17 Thread Denis Feklushkin via Digitalmars-d-learn

On Friday, 17 December 2021 at 18:02:52 UTC, Tejas wrote:

I improved your sample:

```d
immutable struct S
{
~this() {}
}

immutable struct S2
{
S sss;
~this() {}
}

void main()
{
S2 s = S2();
}
```

```
Error: `immutable` method `serializer_bug.S.~this` is not 
callable using a mutable object
Error: mutable method `serializer_bug.S2.~this` is not callable 
using a `immutable` object
serializer_bug.d(17,5):Consider adding `const` or `inout` 
here

```

immutable dtor can't be called at all?



Re: This is bug or not? (immutable class containing struct with dtor)

2021-12-17 Thread Tejas via Digitalmars-d-learn
On Friday, 17 December 2021 at 18:19:34 UTC, Denis Feklushkin 
wrote:

On Friday, 17 December 2021 at 18:01:03 UTC, Tejas wrote:


I think since `immutable` objects are kept in Read Only Storage


Some of them can be stored in ROM in some cases, but actually 
"immutable" keyword means "not mutable for whole its lifetime"


Well, it would be really weird if destructors successfully 
executed for some class of `immutable` qualified objects but 
didn't for others.


Not too much of a stretch to imagine that destruction for 
immutable objects was outright disallowed.


Someone who can explain this behaviour more thoroughly would be 
much appreciated 


Maybe we should allow finalizers to mutate their instance?


Re: This is bug or not? (immutable class containing struct with dtor)

2021-12-17 Thread Denis Feklushkin via Digitalmars-d-learn

On Friday, 17 December 2021 at 18:01:03 UTC, Tejas wrote:


I think since `immutable` objects are kept in Read Only Storage


Some of them can be stored in ROM in some cases, but actually 
"immutable" keyword means "not mutable for whole its lifetime"


Re: This is bug or not? (immutable class containing struct with dtor)

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

On Friday, 17 December 2021 at 18:01:03 UTC, Tejas wrote:
On Friday, 17 December 2021 at 17:34:05 UTC, Denis Feklushkin 
wrote:
On Friday, 17 December 2021 at 17:27:53 UTC, Denis Feklushkin 
wrote:



[...]


("serializer_bug" is just name of my local .d file)


I think since `immutable` objects are kept in Read Only 
Storage, you can't call destructors on them since the objects 
don't get erased when `~this` is called, but rather they get 
assigned their `.init` value, which tells the GC that they can 
be collected.


`immutable class` has nothing to do with it, even the following 
fails to compile:

```d



struct S
{
    ~this() immutable {}
}

void main()
{
S s = S();
}

Error: `immutable` method `onlineapp.S.~this` is not callable 
using a mutable object

```


Correction:
`immutable S s = S();` inside the `void main()`


Re: This is bug or not? (immutable class containing struct with dtor)

2021-12-17 Thread Tejas via Digitalmars-d-learn
On Friday, 17 December 2021 at 17:34:05 UTC, Denis Feklushkin 
wrote:
On Friday, 17 December 2021 at 17:27:53 UTC, Denis Feklushkin 
wrote:


~this() {} // Comment out this to fix this compilation  
error:

// Error: `immutable` method `serializer_bug.Imm.~this` is


("serializer_bug" is just name of my local .d file)


I think since `immutable` objects are kept in Read Only Storage, 
you can't call destructors on them since the objects don't get 
erased when `~this` is called, but rather they get assigned their 
`.init` value, which tells the GC that they can be collected.


`immutable class` has nothing to do with it, even the following 
fails to compile:

```d



struct S
{
    ~this() immutable {}
}

void main()
{
S s = S();
}

Error: `immutable` method `onlineapp.S.~this` is not callable 
using a mutable object

```



Re: This is bug or not? (immutable class containing struct with dtor)

2021-12-17 Thread Denis Feklushkin via Digitalmars-d-learn
On Friday, 17 December 2021 at 17:27:53 UTC, Denis Feklushkin 
wrote:


~this() {} // Comment out this to fix this compilation  
error:

// Error: `immutable` method `serializer_bug.Imm.~this` is


("serializer_bug" is just name of my local .d file)



This is bug or not? (immutable class containing struct with dtor)

2021-12-17 Thread Denis Feklushkin via Digitalmars-d-learn

```d
/+ dub.json:
{
  "name": "test",
  "dependencies": {
  }
}
+/

struct S
{
~this() {}
}

immutable class Imm
{
S s; // this is immutable value because whole class is 
immutable


this()
{
s = S();
}

~this() {} // Comment out this to fix this compilation  error:
// Error: `immutable` method `serializer_bug.Imm.~this` is 
not callable using a mutable object

// What mutable object is meant here?
}


void main()
{
auto ic = new immutable Imm();
}
```

Run: $ dub --single bug.d


Re: Efficient way to create/copy immutable struct instance with modified data

2021-11-19 Thread Adam D Ruppe via Digitalmars-d-learn

On Friday, 19 November 2021 at 17:38:53 UTC, Merlin Diavova wrote:
I'm trying to figure out the most efficient way to create 
modified instances of immutable structs.


This might not be the best way but it is a kinda cool trick 
anyway: structs have a `tupleof` property you can slice. So you 
can do things like:


Node(old_node.tupleof[0 .. argIndex], replacement, 
old_node.tupleof[argIndex + 1 .. $]);


Where argIndex can be like 0 to replace the first item in the 
struct, or 1 to replace the second.


It is possible to look this up using reflection and kinda 
automate this if you wanted.


```
mixin template Replaceable() {
// returns a replaced thing when you use it as 
`with_someField`
typeof(this) opDispatch(string s, T)(T replacement) 
if(s.length > 5 && s[0 .. 5] == "with_")

{
static foreach(idx, member; typeof(this).tupleof) 
{
static if(__traits(identifier, member) == 
s[5 .. $])

enum argIndex = idx;
}
// if the arg is not found you will get an ugly 
error message here about undefined

// argIndex meh.
return typeof(this)(this.tupleof[0 .. argIndex], 
replacement, this.tupleof[argIndex + 1 .. $]);

    }
}

immutable struct Node {
string label;
Node* parentNode;
int port;

mixin Replaceable; // add the ugly generic code from the 
top

}

void main() {
Node i = Node("one", null, 4);
Node i2 = i.with_port(6); // and now use it like this
assert(i2.label == "one");
assert(i2.port == 6);
}
```


I did `with_` instead of camelCase to avoid having to mess with 
case comparisons on the name.


Efficient way to create/copy immutable struct instance with modified data

2021-11-19 Thread Merlin Diavova via Digitalmars-d-learn

Hi all,

I'm trying to figure out the most efficient way to create 
modified instances of immutable structs.


Currently, I'm doing the following:

```d
immutable struct Node {
string label;
Node parentNode;
NetworkPort port;

auto withLabel(string newLabel)
{
return Node(newLabel, this.parentNode, this.port);
}

auto withParentNode(Node newParentNode)
{
return Node(this.label, newParentNode, this.port);
}

auto withNetworkPort(NetworkPort newPort)
{
return Node(this.label, this.parentNode, newPort);
}
}
```
Coming from a scripting language the above makes the most sense.
In D, this an efficient way to do it? Are there any best 
practices around this?


Thanks in advance

Merlin


Re: Run-time setting of immutable variable?

2021-09-03 Thread DLearner via Digitalmars-d-learn
On Thursday, 2 September 2021 at 23:12:28 UTC, Steven 
Schveighoffer wrote:



[...]
immutable means "I can never change and *everything I point at* 
can never change".

[...]

If that is how the language defines the keyword 'immutable' when 
used in the definition of a pointer variable, then so be it.


I would, however, suggest that the additional 
'action-at-a-distance' implication (freezing not just the 
variable itself, but also it's target) is inconsistent with the 
definition of 'immutable' with other variable types.


Surely it would be better to reserve 'immutable' on a pointer to 
mean simply set-once on the pointer itself (with no implications 
for whatever the pointer is pointing to), and another keyword 
('blocked'?) for the current definition?





Re: Run-time setting of immutable variable?

2021-09-02 Thread Ali Çehreli via Digitalmars-d-learn

On 9/2/21 9:01 AM, DLearner wrote:
Suppose there is a variable that is set once per run, and is (supposed) 
never to be altered again.


An accessor function can be a solution, which supports your other 
comment about data potentially mutating by other means:


// Assume these are in a module
// 

// This is private; you can even name it arr_.
private
ubyte[10] arr;

// This is the accessor:
public
const(ubyte)* arrPtr() {
  return arr.ptr;
}
// 

void main() {
  *arrPtr = 42;  // Compilation ERROR; good.
}

Ali


Re: Run-time setting of immutable variable?

2021-09-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/2/21 1:17 PM, DLearner wrote:


I am looking for a mutable Arr but would like an immutable ArrPtr.


Then you want const not immutable.

Here is the reason:

```d
void main()
{
int x = 5;
immutable int *ptr = cast(immutable int *)
assert(*ptr == 5); // ok
x = 6;
assert(*ptr == 5); // what happens here?
}
```

Depending on optimizations and compiler constant folding, that second 
assert may pass.


immutable means "I can never change and *everything I point at* can 
never change". The compiler is free to use this knowledge to avoid 
redoing calculations it has already done. I tknows that `*ptr == 5` 
already, and that can never change, so it just doesn't even bother with 
the second assert.


However, make ptr *const*, and now not only do you not need the cast, 
but the second assert will fail as expected.



```
`Arr` is not immutable, so `ArrPtr` shouldn't point at it if it's 
immutable.

```
Surely there is no inconsistency - at run time the array is in a fixed 
place,  so ArrPtr is (or at least should be) a constant, but the 
contents of the array

can vary as the program runs.


In D, const and immutable are transitive, which means that you can't 
have a pointer that is const, but allows changing what it points at. So 
while a const pointer *may* work for your purposes, you may want a 
specialized type, or a property function. It depends on how you intend 
to use `ArrPtr`. Others have given good answers to this problem.


-Steve


Re: Run-time setting of immutable variable?

2021-09-02 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Sep 02, 2021 at 05:17:15PM +, DLearner via Digitalmars-d-learn 
wrote:
[...]
> The following clean-compiled and produced the expected result:
> ```
> ubyte[10] Arr;
> 
> immutable void* ArrPtr;
>   shared static this() {
>   ArrPtr = cast(immutable void*)([0]);
>   }

Casting this to immutable is unsafe, because Arr is actually mutable. In
D, const and immutable are transitive, so when you cast a pointer into
immutable, you're basically promising that *both* the pointer *and* the
data pointed to will never change. The compiler is free to assume that
the data pointed to will never change, which may cause consistency
problems if the data *does* change later.

In cases like this, const is a better choice: const ensures that the
pointer will not mutate and the pointed-to data cannot be mutated
through this pointer, but the data *may* be mutated through another
reference (e.g., by modifying Arr directly).


[...]
> I am looking for a mutable Arr but would like an immutable ArrPtr.

In D, const and immutable are transitive, so you cannot do this (but see
below).


> ```
> `Arr` is not immutable, so `ArrPtr` shouldn't point at it if it's
> immutable.
> ```
> Surely there is no inconsistency - at run time the array is in a fixed
> place,  so ArrPtr is (or at least should be) a constant, but the
> contents of the array can vary as the program runs.

In this case, what you want is const, not immutable.  Const means you
cannot modify the pointer, and you cannot mutate the data through this
pointer, but you *can* modify the array from a mutable reference.


T

-- 
You are only young once, but you can stay immature indefinitely. -- azephrahel


Re: Run-time setting of immutable variable?

2021-09-02 Thread jfondren via Digitalmars-d-learn

On Thursday, 2 September 2021 at 17:17:15 UTC, DLearner wrote:
Surely there is no inconsistency - at run time the array is in 
a fixed place,  so ArrPtr is (or at least should be) a 
constant, but the contents of the array

can vary as the program runs.


In the case of `immutable(T)* ArrPtr`, the contents of the 
pointed-to array cannot vary as the program runs. If it's 
immutable, nothing in the program ever mutates it. In the case of 
`const(T)* ArrPtr`, the contents of the pointed-to array can vary 
as the program runs, and the only restriction is that the array 
can't be mutated through ArrPtr.


If what you mean is that you want the *pointer* to never change, 
`T * const ArrPtr` in C syntax, but that you don't care if the 
pointed-to array changes via ArrPtr or any other reference, then 
I don't think D can express this. You could make ArrPtr a 
function:


```d
void main() {
int[] xs = [1, 2, 3, 4];
int* p() { return [2]; }
p[0] = 0;
assert(xs == [1, 2, 0, 4]);
p++; // Error: ... not an lvalue and cannot be modified
}
```


Re: Run-time setting of immutable variable?

2021-09-02 Thread Kagamin via Digitalmars-d-learn

If you want only address, you can keep it as size_t:

ubyte[10] Arr;
immutable size_t Address;
static this() {
Address = cast(size_t)([0]);
}


Re: Run-time setting of immutable variable?

2021-09-02 Thread DLearner via Digitalmars-d-learn
On Thursday, 2 September 2021 at 16:46:46 UTC, Steven 
Schveighoffer wrote:

On 9/2/21 12:01 PM, DLearner wrote:
Suppose there is a variable that is set once per run, and is 
(supposed) never to be altered again.  However, the value to 
which it is set is not known at compile time.

Example below, variable is 'ArrPtr';
```
ubyte[10] Arr;

// immutable void* ArrPtr;
void* ArrPtr;

void main() {

    ArrPtr = cast(void*)Arr[0];

// modify ArrPtr>


}
```
Is there a way of getting D to guarantee that ArrPtr is never 
modified after

```
    ArrPtr = cast(void*)Arr[0];
```]


You shouldn't be doing this. `Arr` is not immutable, so 
`ArrPtr` shouldn't point at it if it's immutable.


If you want to guarantee that `ArrPtr` never changes once set, 
yet still want it to point at mutable data, you need to use a 
type that does that (like a head mutable or "write once" type), 
which I believe doesn't exist in phobos.


If you don't actually need to mutate the data via `ArrPtr`, you 
can make it const, and use H.S. Teoh's solution. But you should 
not use immutable, as the compiler implies that data pointed at 
is also immutable (and of course, you won't need casting). Make 
sure you use regular `static this`, not `shared static this`, 
as your fields are thread-local, not shared.


-Steve


The following clean-compiled and produced the expected result:
```
ubyte[10] Arr;

immutable void* ArrPtr;
shared static this() {
ArrPtr = cast(immutable void*)([0]);
}

void main() {

  import std.stdio;
  void* ArrPtr2;

  ArrPtr2 = cast(void*)([0]);

  writeln("ArrPtr = ", ArrPtr);
  writeln("ArrPtr2 = ", ArrPtr2);  // consistency test

//  ArrPtr = ArrPtr + 1;  // mutability test - compile 
(correctly) failed when uncommented.

  ArrPtr2 = ArrPtr2 + 1;

  Arr[1] = 4;
  Arr[1] = 7;  // mutability test   
}
```

The following produced deprecated warnings, but still seemed to 
work:

```
ubyte[10] Arr;

immutable void* ArrPtr;
static this() {
    ArrPtr = cast(immutable void*)([0]);
}

void main() {

  import std.stdio;
  void* ArrPtr2;

  ArrPtr2 = cast(void*)([0]);

  writeln("ArrPtr = ", ArrPtr);
  writeln("ArrPtr2 = ", ArrPtr2);  // consistency test

//  ArrPtr = ArrPtr + 1;  // mutability test on ArrPtr - 
compile (correctly) failed when uncommented.

  ArrPtr2 = ArrPtr2 + 1;

  Arr[1] = 4;
  Arr[1] = 7;  // mutability test on Arr
}
```
I am looking for a mutable Arr but would like an immutable ArrPtr.

```
`Arr` is not immutable, so `ArrPtr` shouldn't point at it if it's 
immutable.

```
Surely there is no inconsistency - at run time the array is in a 
fixed place,  so ArrPtr is (or at least should be) a constant, 
but the contents of the array

can vary as the program runs.


Re: Run-time setting of immutable variable?

2021-09-02 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/2/21 12:01 PM, DLearner wrote:
Suppose there is a variable that is set once per run, and is (supposed) 
never to be altered again.  However, the value to which it is set is not 
known at compile time.

Example below, variable is 'ArrPtr';
```
ubyte[10] Arr;

// immutable void* ArrPtr;
void* ArrPtr;

void main() {

    ArrPtr = cast(void*)Arr[0];

// 

}
```
Is there a way of getting D to guarantee that ArrPtr is never modified 
after

```
    ArrPtr = cast(void*)Arr[0];
```]


You shouldn't be doing this. `Arr` is not immutable, so `ArrPtr` 
shouldn't point at it if it's immutable.


If you want to guarantee that `ArrPtr` never changes once set, yet still 
want it to point at mutable data, you need to use a type that does that 
(like a head mutable or "write once" type), which I believe doesn't 
exist in phobos.


If you don't actually need to mutate the data via `ArrPtr`, you can make 
it const, and use H.S. Teoh's solution. But you should not use 
immutable, as the compiler implies that data pointed at is also 
immutable (and of course, you won't need casting). Make sure you use 
regular `static this`, not `shared static this`, as your fields are 
thread-local, not shared.


-Steve


Re: Run-time setting of immutable variable?

2021-09-02 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Sep 02, 2021 at 04:01:19PM +, DLearner via Digitalmars-d-learn 
wrote:
> Suppose there is a variable that is set once per run, and is
> (supposed) never to be altered again.  However, the value to which it
> is set is not known at compile time.

This is the classic use case of `immutable`.  Using the example you
gave, you'd move the initialization of ArrPtr into a static module
constructor:

immutable void* ArrPtr;
shared static this() {
ArrPtr = ...; // initialize it here
}

void main() {
... // ArrPtr is immutable from here on.
}


T

-- 
Дерево держится корнями, а человек - друзьями.


Run-time setting of immutable variable?

2021-09-02 Thread DLearner via Digitalmars-d-learn
Suppose there is a variable that is set once per run, and is 
(supposed) never to be altered again.  However, the value to 
which it is set is not known at compile time.

Example below, variable is 'ArrPtr';
```
ubyte[10] Arr;

// immutable void* ArrPtr;
void* ArrPtr;

void main() {

   ArrPtr = cast(void*)Arr[0];

// ArrPtr>


}
```
Is there a way of getting D to guarantee that ArrPtr is never 
modified after

```
   ArrPtr = cast(void*)Arr[0];
```

Best regards


Re: Creating immutable arrays in @safe code

2021-07-18 Thread zjh via Digitalmars-d-learn

On Sunday, 18 July 2021 at 10:02:07 UTC, ag0aep6g wrote:

On 17.07.21 15:56, ag0aep6g wrote:


+1.
IMO,`strong pure` is `the outside world` has no impact on me. 
`Funcs` don't have any `indirect`.


Re: Creating immutable arrays in @safe code

2021-07-18 Thread ag0aep6g via Digitalmars-d-learn

On 17.07.21 15:56, ag0aep6g wrote:
At a glance, the only meaningful use of `PURE.strong` seems to be in 
dcast.d, introduced by the PR you linked. Changing that to `PURE.const_` 
doesn't break any tests for me. So I'm inclined to believe that 
`PURE.strong` is nonsense, and that `PURE.const_` already means 
"strongly pure".


However, changing that instance doesn't fix the issue. Apparently, DMD 
doesn't even recognize


     int[] array(const int[] input) pure { ... }

as `PURE.const_`.


I've dug a bit deeper, and apparently I'm to blame for confusing things. 
In issue 15862 [1], I stated that functions with mutable indirections in 
the return type cannot be strongly pure. That's wrong, but it seems to 
have found its way into DMD.


The core of issue 15862 is true: Two calls to `array` cannot be merged 
into one. But that doesn't make it weakly pure. Mutability in the return 
type is distinct from weak/strong purity.


These are all true:

* `array` is "strongly pure".
* `array` is a "pure factory function".
* The result of one call to `array` cannot be reused for another, 
identical call.



[1] https://issues.dlang.org/show_bug.cgi?id=15862.


Re: Creating immutable arrays in @safe code

2021-07-17 Thread ag0aep6g via Digitalmars-d-learn

On 17.07.21 14:56, Dennis wrote:

On Saturday, 17 July 2021 at 12:05:44 UTC, ag0aep6g wrote:
Hm, as far as I understand, "strongly pure" doesn't require 
`immutable` parameters. `const` should be enough. The spec says: "A 
strongly pure function has no parameters with mutable indirections" [1].


I just took the description from the source code:
```D
enum PURE : ubyte
{
     impure  = 0,    // not pure at all
     fwdref  = 1,    // it's pure, but not known which level yet
     weak    = 2,    // no mutable globals are read or written
     const_  = 3,    // parameters are values or const
     strong  = 4,    // parameters are values or immutable
}
```


That looks off to me. Unless DMD has some secret knowledge about a 
shortcoming in the established definition of "strongly pure", I think 
those enum values are badly named.


At a glance, the only meaningful use of `PURE.strong` seems to be in 
dcast.d, introduced by the PR you linked. Changing that to `PURE.const_` 
doesn't break any tests for me. So I'm inclined to believe that 
`PURE.strong` is nonsense, and that `PURE.const_` already means 
"strongly pure".


However, changing that instance doesn't fix the issue. Apparently, DMD 
doesn't even recognize


int[] array(const int[] input) pure { ... }

as `PURE.const_`.


I don't know whether the spec or code is correct.


When it comes to purity, another piece in the puzzle is David 
Nadlinger's article:


https://klickverbot.at/blog/2012/05/purity-in-d/

There, a function with a `const int[]` parameter is described as 
"strongly pure".


As far as I can remember, when DMD and that article disagreed in the 
past, DMD was wrong.


[...]
Yup, [remember 
this](https://github.com/dlang/dmd/pull/8035#discussion_r174771516)?


Hehe, I knew I had complained about it before.

It's doubly bad: (1) We're missing out on bug fixes, because they're 
hidden behind `-preview=dip1000` for no reason. (2) When 
`-preview=dip1000` ever becomes the default, code will break that 
doesn't even use the features of DIP 1000.


Re: Creating immutable arrays in @safe code

2021-07-17 Thread rikki cattermole via Digitalmars-d-learn



On 18/07/2021 12:56 AM, Dennis wrote:

I don't know whether the spec or code is correct.


Unless otherwise specified, the code is authoritative.


Re: Creating immutable arrays in @safe code

2021-07-17 Thread Dennis via Digitalmars-d-learn

On Saturday, 17 July 2021 at 12:05:44 UTC, ag0aep6g wrote:
Hm, as far as I understand, "strongly pure" doesn't require 
`immutable` parameters. `const` should be enough. The spec 
says: "A strongly pure function has no parameters with mutable 
indirections" [1].


I just took the description from the source code:
```D
enum PURE : ubyte
{
impure  = 0,// not pure at all
fwdref  = 1,// it's pure, but not known which level 
yet

weak= 2,// no mutable globals are read or written
const_  = 3,// parameters are values or const
strong  = 4,// parameters are values or immutable
}
```
I don't know whether the spec or code is correct.

Also, conflating other issues with DIP1000 is such an obviously 
terrible idea.


Yup, [remember 
this](https://github.com/dlang/dmd/pull/8035#discussion_r174771516)?





Re: Creating immutable arrays in @safe code

2021-07-17 Thread ag0aep6g via Digitalmars-d-learn

On 17.07.21 13:05, Dennis wrote:
There used to be a complex `isReturnIsolated` check, but the [fix for 
issue 15660](https://github.com/dlang/dmd/pull/8048) reduced it to a 
check 'is the function strongly `pure`' which means 'parameters are 
values or immutable'. To reduce code breakage, the 'strong pure' 
requirement is only needed with -dip1000, which is why your example 
doesn't work with it.


Hm, as far as I understand, "strongly pure" doesn't require `immutable` 
parameters. `const` should be enough. The spec says: "A strongly pure 
function has no parameters with mutable indirections" [1]. Seems to me 
that the fix is buggy.


Also, conflating other issues with DIP1000 is such an obviously terrible 
idea.



[1] https://dlang.org/spec/function.html#pure-functions


Re: Creating immutable arrays in @safe code

2021-07-17 Thread Dennis via Digitalmars-d-learn

On Saturday, 17 July 2021 at 05:44:24 UTC, ag0aep6g wrote:
I tried doing that, but `-preview=dip1000` causes trouble. This 
fails:

(...)
I'm not sure what's going on.


I'm not completely caught up, but from what I see, pure and 
immutable have a history of issues:


[Issue 11503 - Type system breaking caused by implicit conversion 
for the value returned from pure 
function](https://issues.dlang.org/show_bug.cgi?id=11503)
[Issue 11909 - Struct members and static arrays break pure 
function escape analysis (immutability 
violation)](https://issues.dlang.org/show_bug.cgi?id=11909)
[Issue 15660 - break immutable with pure function and mutable 
reference params](https://issues.dlang.org/show_bug.cgi?id=15660)


There used to be a complex `isReturnIsolated` check, but the [fix 
for issue 15660](https://github.com/dlang/dmd/pull/8048) reduced 
it to a check 'is the function strongly `pure`' which means 
'parameters are values or immutable'. To reduce code breakage, 
the 'strong pure' requirement is only needed with -dip1000, which 
is why your example doesn't work with it.


Re: Creating immutable arrays in @safe code

2021-07-16 Thread ag0aep6g via Digitalmars-d-learn

On 17.07.21 00:27, H. S. Teoh wrote:

Hmm, OK. Not sure why .array isn't being inferred as unique... but yeah,
you probably have to resort to using @trusted with .assumeUnique.


In addition to `pure`, you also need a const/immutable input and a 
mutable output, so that the output cannot be a slice of the input.


For std.array.array it might be possible to carefully apply `Unqual` to 
the element type.


I tried doing that, but `-preview=dip1000` causes trouble. This fails:


int[] array(const int[] input) pure nothrow @safe
{
int[] output;
foreach (element; input) output ~= element;
return output;
}
void main() pure nothrow @safe
{
const int[] c = [1, 2, 3];
immutable int[] i = array(c);
/* Without `-preview=dip1000`: works, because the result is unique.
With `-preview=dip1000`: "Error: cannot implicitly convert". */
}


I'm not sure what's going on. `pure` being involved makes me think of 
issue 20150. But it also fails with my fix for that issue. So maybe it's 
another bug.


  1   2   3   4   5   6   7   8   9   10   >