Re: getting rid of immutable (or const)

2019-09-06 Thread berni via Digitalmars-d-learn

On Friday, 6 September 2019 at 08:47:07 UTC, Kagamin wrote:
Physical objects work like reference types. A place on 
bookshelf is at one coordinate and a book is at another 
coordinate, you don't copy the book, you fill a place on 
bookshelf with a reference to the book.


So it's more like a piece of paper, where there is place for a 
note. And when assigning, I erase that note (whatever it was) and 
write the new note at that place. Got it! :-)


Re: getting rid of immutable (or const)

2019-09-06 Thread berni via Digitalmars-d-learn

On Thursday, 5 September 2019 at 21:22:12 UTC, Ali Çehreli wrote:
If it makes for the type to have immutable (or const) members, 
then fine; with the understanding that objects of that type 
cannot be assigned or mutated any other way, we can define them 
like that. What I meant is, because we want to use such a type 
in an AA and we don't want the element to change should not 
dictate the type's members. Using in an AA should be yet 
another usage of the type.


Got it. ;-)


> if immutable were that useless, why would it exist
> at all?

immutable is useful: You can have immutable objects, immutable 
AAs (different from what we are discussing here), etc.


So, what I'm just trying all the time is not to have a struct 
with immutable elements but a immutable struct-object with 
mutable elements. I think, that's what I confused all the time.


As a general rule, I never make members const or immutable; 
this is a guideline that I carried over from C++.


I have almost no experience with C++, but I just accept that as a 
good advise. After all that discussion here, it seems to be sound.


Thank you very much too! I think I made a big jump forward in 
understanding the concept of immutability in the last 24 hours. 
:-)


Re: getting rid of immutable (or const)

2019-09-06 Thread berni via Digitalmars-d-learn

On Thursday, 5 September 2019 at 20:10:03 UTC, ag0aep6g wrote:
You're not putting an immutable int into an AA. You're copying 
the value of an immutable int to a mutable one.


but I can't do that with a struct, having an immutable member. 
When I remove that immutable inside of the struct it works. ?!?


`Point` is effectively the same as `immutable long`. A better 
simile would be this: `immutable(int)[int] a; a[1] = 17;`. And 
now you get the same error. You can't overwrite the element, 
because its immutable.


Ah, the point is not, that my object contains an immutable 
element, but that the base type of the AA is a type with an 
immutable element! I understand now. Thanks a lot!


Re: getting rid of immutable (or const)

2019-09-06 Thread Kagamin via Digitalmars-d-learn

On Thursday, 5 September 2019 at 12:46:06 UTC, berni wrote:
OK. This are two solutions and although I'll probably not going 
to use any of those (due to other reasons), I still don't 
understand, why the original approach does not work. If I've 
got a book an put it in a box and later I'll get it out again, 
it's still the same book. So why has a struct changed when I 
put it into an AA and get it out again? It's not supposed to 
change...


Physical objects work like reference types. A place on bookshelf 
is at one coordinate and a book is at another coordinate, you 
don't copy the book, you fill a place on bookshelf with a 
reference to the book.


Re: getting rid of immutable (or const)

2019-09-05 Thread Ali Çehreli via Digitalmars-d-learn

On 09/05/2019 12:51 PM, berni wrote:

>> int[int] a;
>>
>> immutable int b = 17;
>> a[1] = b;  // <-- expecting error here

As explained elsewhere, a[1] is a mutable int. That assignment is 
copying b on top of the element.


>> const oldPointer = (1 in a);
>> immutable int c = 10;
>> a[1] = c;
>> assert(oldPointer is (1 in a));
>>
>> Point[int] d;
>>
>> immutable Point e = Point(17);
>> d[1] = e;   // <-- but error is here

That is the equivalent of

  d[1].x = e.x;

It can't work because the left-hand side is immutable. (immutable or 
const members make objects of those types unassignable.)


>> const or immutable members make structs unassignable.
>
> But why? Here:

Otherwise the immutability guarantees woul be violated.

I understand your questioning the AA design but at the lowest level it's 
just assignment operation. I understand that it could be "emplacement" 
on top of the existing element but the guarantees would be violated even 
then because the 'in' operator returns a pointer. Placing a new object 
on the same address would make existing pointer-holders unhappy.


> I understand, that I cannot change f[0], because it's allready got a
> default value and that value would be overwritten. But in an aa, that
> member does not exist before putting the Point in there, hence there is
> nothing, that could be overwritten...

Yeah, it's highly likely just assignment on a default-valued object.

>> Whether the members of a type are const or immutable should not be
>> dictated by where the objects of that type will be used. If it makes
>> sense otherwise, sure...
>
> I'm not sure if I understand that right. It's sort of an advice on how
> to decide if one want's to make a member immutable or not, is it?

If it makes for the type to have immutable (or const) members, then 
fine; with the understanding that objects of that type cannot be 
assigned or mutated any other way, we can define them like that. What I 
meant is, because we want to use such a type in an AA and we don't want 
the element to change should not dictate the type's members. Using in an 
AA should be yet another usage of the type.


> if immutable were that useless, why would it exist
> at all?

immutable is useful: You can have immutable objects, immutable AAs 
(different from what we are discussing here), etc.


You can use immutable at a different level: not members but their 
members can be immutable. For example, a 'string' member would not be 
immutable itself but its chars would be immutable. There is no problem 
in having an AA with types having such a member:


struct Person {
  string name;
}

You can assign to Person objects but their names are immutable. If you 
wanted a Person where the name should never change, then you could make 
a const(Person), immutable(Person), or provide read-only access to 
'name', etc.


> So I would like to understand, what's happening; being able to
> predict, what works and what not. At the moment it's almost always the
> opposite of what I think it should be...

As a general rule, I never make members const or immutable; this is a 
guideline that I carried over from C++. A recent issue I had with const 
members in C++ has been silent skipping of move assignment of objects. 
Unless one uses functional programming style, that's how it should be in 
D as well. Otherwise, assignment is disabled and AAs don't work as 
expected because they use assignment under the hood as well.


Ali



Re: getting rid of immutable (or const)

2019-09-05 Thread ag0aep6g via Digitalmars-d-learn

On 05.09.19 21:51, berni wrote:

void main()
{
    int[int] a;

    immutable int b = 17;
    a[1] = b;  // <-- expecting error here
    const oldPointer = (1 in a);
    immutable int c = 10;
    a[1] = c;
    assert(oldPointer is (1 in a));

    Point[int] d;

    immutable Point e = Point(17);
    d[1] = e;   // <-- but error is here
}

struct Point
{
    immutable int x;
}


What's the difference? I can put an immutable int in an AA and I can 
overwrite it (pointer is still the same),


You're not putting an immutable int into an AA. You're copying the value 
of an immutable int to a mutable one.


but I can't do that with a 
struct, having an immutable member. When I remove that immutable inside 
of the struct it works. ?!?


`Point` is effectively the same as `immutable long`. A better simile 
would be this: `immutable(int)[int] a; a[1] = 17;`. And now you get the 
same error. You can't overwrite the element, because its immutable.


You could argue that there is no element before assigning (initializing) 
`d[1]` for the first time. So the assignment should go through the first 
time, and it should only be an error when you try to write a second 
time. But figuring that out mechanically is hard, and DMD isn't smart 
enough to do it. So, to be on the safe side, it just says that you can't 
do that at all.


Re: getting rid of immutable (or const)

2019-09-05 Thread berni via Digitalmars-d-learn

On Thursday, 5 September 2019 at 15:48:40 UTC, Ali Çehreli wrote:
That's the misunderstanding: The existing object is assigned 
over. The address is the same:


void main() {
  int[int] aa;
  aa[1] = 1;
  const oldPointer = (1 in aa);
  aa[1] = 11;
  assert(oldPointer is (1 in aa));  // Passes
}


First, I thought, I've got understood it now, but then I wrote 
this little program and the result was not, what I thought it 
would be:



void main()
{
int[int] a;

immutable int b = 17;
a[1] = b;  // <-- expecting error 
here

const oldPointer = (1 in a);
immutable int c = 10;
a[1] = c;
assert(oldPointer is (1 in a));

Point[int] d;

immutable Point e = Point(17);
d[1] = e;   // <-- but error is here
}

struct Point
{
immutable int x;
}


What's the difference? I can put an immutable int in an AA and I 
can overwrite it (pointer is still the same), but I can't do that 
with a struct, having an immutable member. When I remove that 
immutable inside of the struct it works. ?!?


While writing this, I had an other idea, namely, that changing 
d[1] would make e to be something different (x inside Point is 
mutable this time):



Point e = Point(17);
d[1] = e;
d[1] = Point(19);
writeln(e);


But it's still 17.



const or immutable members make structs unassignable.


But why? Here:


Point[3] f;
f[0] = Point(3);


I understand, that I cannot change f[0], because it's allready 
got a default value and that value would be overwritten. But in 
an aa, that member does not exist before putting the Point in 
there, hence there is nothing, that could be overwritten...


Whether the members of a type are const or immutable should not 
be dictated by where the objects of that type will be used. If 
it makes sense otherwise, sure...


I'm not sure if I understand that right. It's sort of an advice 
on how to decide if one want's to make a member immutable or not, 
is it?


If you are worried about existing elements being modified, you 
can provide a different container that wraps an AA, but 
provides an opIndex that returns 'ref const(T)'. That would 
solve the immutability of the elements in the container.


No, I don't worry about such things. My program runs smoothly 
when I don't make that members immutable. And I could perfectly 
live with that But that's the maxim I used the last three years: 
"If avoidable, don't use 'immutable' at all, it only causes 
problems." But that is not satisfiable. Because if immutable were 
that useless, why would it exist at all? So I would like to 
understand, what's happening; being able to predict, what works 
and what not. At the moment it's almost always the opposite of 
what I think it should be...




Re: getting rid of immutable (or const)

2019-09-05 Thread Ali Çehreli via Digitalmars-d-learn

On 09/05/2019 07:31 AM, berni wrote:
> On Thursday, 5 September 2019 at 13:27:55 UTC, drug wrote:
>> [...]when you put it into an AA you modify old value
>
> Why?!? :-o When putting it into an AA it will be copied to a different
> place in memory,

That's the misunderstanding: The existing object is assigned over. The 
address is the same:


void main() {
  int[int] aa;
  aa[1] = 1;
  const oldPointer = (1 in aa);
  aa[1] = 11;
  assert(oldPointer is (1 in aa));  // Passes
}

> but the value is still the same, it's not modified.

const or immutable members make structs unassignable.

Whether the members of a type are const or immutable should not be 
dictated by where the objects of that type will be used. If it makes 
sense otherwise, sure...


If you are worried about existing elements being modified, you can 
provide a different container that wraps an AA, but provides an opIndex 
that returns 'ref const(T)'. That would solve the immutability of the 
elements in the container.


Ali



Re: getting rid of immutable (or const)

2019-09-05 Thread drug via Digitalmars-d-learn

05.09.2019 17:31, berni пишет:

On Thursday, 5 September 2019 at 13:27:55 UTC, drug wrote:

[...]when you put it into an AA you modify old value


Why?!? :-o When putting it into an AA it will be copied to a different 
place in memory, but the value is still the same, it's not modified. 
Sorry, but I still think, there is something fundamentally wrong about 
how I think about immutability.
Because structs are value types - assigning new value to old value means 
the old value modification. In case of reference types like pointers or 
classes assigning new value to old one also means modifying old value 
but this old value is a reference to value so in case of reference types 
only reference modified but the value isn't




But if you just want to initialize an AA by immutable members then 
this can be usefull to read 
https://dlang.org/spec/hash-map.html#runtime_initialization


Well, yes and no. I want to initialize an AA with structs that contain 
immutable members. And that AA resides at runtime inside of a function 
body. I don't see, how this can be done with he approach given by the 
link. :-(




Re: getting rid of immutable (or const)

2019-09-05 Thread berni via Digitalmars-d-learn

On Thursday, 5 September 2019 at 13:27:55 UTC, drug wrote:

[...]when you put it into an AA you modify old value


Why?!? :-o When putting it into an AA it will be copied to a 
different place in memory, but the value is still the same, it's 
not modified. Sorry, but I still think, there is something 
fundamentally wrong about how I think about immutability.


But if you just want to initialize an AA by immutable members 
then this can be usefull to read 
https://dlang.org/spec/hash-map.html#runtime_initialization


Well, yes and no. I want to initialize an AA with structs that 
contain immutable members. And that AA resides at runtime inside 
of a function body. I don't see, how this can be done with he 
approach given by the link. :-(


Re: getting rid of immutable (or const)

2019-09-05 Thread drug via Digitalmars-d-learn

05.09.2019 15:46, berni пишет:

On Thursday, 5 September 2019 at 12:15:51 UTC, drug wrote:
One solution could be using either pointer to `const(Point)` or class 
here (to avoid pointer using) https://run.dlang.io/is/rfKKAJ


OK. This are two solutions and although I'll probably not going to use 
any of those (due to other reasons), I still don't understand, why the 
original approach does not work. If I've got a book an put it in a box 
and later I'll get it out again, it's still the same book. So why has a 
struct changed when I put it into an AA and get it out again? It's not 
supposed to change...
Because structs are value types so when you put it into an AA you modify 
old value and because it is const/immutable compiler gives an error.


But if you just want to initialize an AA by immutable members then this 
can be usefull to read 
https://dlang.org/spec/hash-map.html#runtime_initialization


Re: getting rid of immutable (or const)

2019-09-05 Thread berni via Digitalmars-d-learn

On Thursday, 5 September 2019 at 12:15:51 UTC, drug wrote:
One solution could be using either pointer to `const(Point)` or 
class here (to avoid pointer using) 
https://run.dlang.io/is/rfKKAJ


OK. This are two solutions and although I'll probably not going 
to use any of those (due to other reasons), I still don't 
understand, why the original approach does not work. If I've got 
a book an put it in a box and later I'll get it out again, it's 
still the same book. So why has a struct changed when I put it 
into an AA and get it out again? It's not supposed to change...


Re: getting rid of immutable (or const)

2019-09-05 Thread drug via Digitalmars-d-learn

05.09.2019 14:28, berni пишет:

On Thursday, 5 September 2019 at 11:22:15 UTC, drug wrote:

05.09.2019 14:17, berni пишет:

Point[long] q;

q[1] = Point(3);


Leads to:

test.d(7): Error: cannot modify struct q[1L] Point with immutable 
members



But why do you try to modify immutable data? What is your point? Could 
you describe you use case?


That's probably, what I don't understand. I've got a Point, which should 
not be modified. I put it in a container (q) and later I get it out 
there again. It should still be the same Point as before. I modify the 
container, not the Point, don't I?


One solution could be using either pointer to `const(Point)` or class 
here (to avoid pointer using) https://run.dlang.io/is/rfKKAJ




Re: getting rid of immutable (or const)

2019-09-05 Thread berni via Digitalmars-d-learn

On Thursday, 5 September 2019 at 11:22:15 UTC, drug wrote:

05.09.2019 14:17, berni пишет:

Point[long] q;

q[1] = Point(3);


Leads to:

test.d(7): Error: cannot modify struct q[1L] Point with 
immutable members



But why do you try to modify immutable data? What is your 
point? Could you describe you use case?


That's probably, what I don't understand. I've got a Point, which 
should not be modified. I put it in a container (q) and later I 
get it out there again. It should still be the same Point as 
before. I modify the container, not the Point, don't I?


Re: getting rid of immutable (or const)

2019-09-05 Thread drug via Digitalmars-d-learn

05.09.2019 14:17, berni пишет:

Point[long] q;

q[1] = Point(3);


Leads to:


test.d(7): Error: cannot modify struct q[1L] Point with immutable members



But why do you try to modify immutable data? What is your point? Could 
you describe you use case?


Re: getting rid of immutable (or const)

2019-09-05 Thread berni via Digitalmars-d-learn

On Thursday, 5 September 2019 at 10:47:56 UTC, Simen Kjærås wrote:

https://dlang.org/library/std/range/retro.html


Yeah, that worked. Thanks. :-)


Don't worry about asking questions


OK. Then here's the next one:


Point[long] q;

q[1] = Point(3);


Leads to:

test.d(7): Error: cannot modify struct q[1L] Point with 
immutable members





Re: getting rid of immutable (or const)

2019-09-05 Thread Simen Kjærås via Digitalmars-d-learn

On Thursday, 5 September 2019 at 09:07:30 UTC, berni wrote:

import std.algorithm: reverse;
writeln(q.reverse);


How to get this working? (I hope I don't annoy you by asking 
that much questions, but I've got the feeling, that I've got 
only two choices: To shy away from using immutable (like I did 
in the last three years) or ask a lot of questions in the hope 
of understanding what's going on...


https://dlang.org/library/std/range/retro.html

Difference is, retro lazily iterates in reverse order, while 
reverse eagerly reverses in-place.


Don't worry about asking questions - it's a good way to learn, 
and we like helping. :) Immutable is not very well supported 
everywhere in the library, sadly. It seems an important building 
block would be something like Reassignable!T, which would hold a 
struct with immutable members, and still be reassignable with 
different values.


--
  Simen


Re: getting rid of immutable (or const)

2019-09-05 Thread berni via Digitalmars-d-learn

On Thursday, 5 September 2019 at 08:56:42 UTC, berni wrote:

[..]


And one more question:


import std.algorithm: reverse;
writeln(q.reverse);


Here the compiler complains with:

test.d(8): Error: template std.algorithm.mutation.reverse 
cannot deduce function from argument types !()(Point[]), 
candidates are:
/usr/include/dmd/phobos/std/algorithm/mutation.d(2483):
std.algorithm.mutation.reverse(Range)(Range r) if 
(isBidirectionalRange!Range && (hasSwappableElements!Range || 
hasAssignableElements!Range && hasLength!Range && 
isRandomAccessRange!Range || isNarrowString!Range && 
isAssignable!(ElementType!Range)))


I allready tried to use q.dup.reverse but that didn't work either.

How to get this working? (I hope I don't annoy you by asking that 
much questions, but I've got the feeling, that I've got only two 
choices: To shy away from using immutable (like I did in the last 
three years) or ask a lot of questions in the hope of 
understanding what's going on...


Re: getting rid of immutable (or const)

2019-09-05 Thread berni via Digitalmars-d-learn

On Thursday, 5 September 2019 at 08:44:35 UTC, berni wrote:

This doesn't compile:

[...]

Any idea, how to get around this?


Found the answer myself: q.map!(a=>a.x).minElement; :-)




Re: getting rid of immutable (or const)

2019-09-05 Thread berni via Digitalmars-d-learn

On Thursday, 5 September 2019 at 08:16:08 UTC, Daniel Kozak wrote:

in this case you can just use:

auto q = cast()p.x;


Ahh, great! :-)

But that directly gets me to the next question:


import std.stdio;

void main()
{
Point[] q = [Point(1),Point(3),Point(2)];

import std.algorithm.searching: minElement;
writeln(q.minElement!(a=>a.x).x);
}

struct Point
{
   @property immutable long x;
}


This doesn't compile:

/usr/include/dmd/phobos/std/algorithm/searching.d(1365): Error: 
cannot modify struct extremeElement Point with immutable members
/usr/include/dmd/phobos/std/algorithm/searching.d(1307): Error: 
template instance `test.main.extremum!(__lambda1, "a < b", 
Point[], Point)` error instantiating
/usr/include/dmd/phobos/std/algorithm/searching.d(3445):
instantiated from here: extremum!(__lambda1, "a < b", Point[])
test.d(8):instantiated from here: minElement!((a) => 
a.x, Point[])


Any idea, how to get around this?


Re: getting rid of immutable (or const)

2019-09-05 Thread Andrew Edwards via Digitalmars-d-learn

On Thursday, 5 September 2019 at 08:16:08 UTC, Daniel Kozak wrote:
On Thu, Sep 5, 2019 at 9:55 AM berni via Digitalmars-d-learn 
 wrote:


I still struggle with the concept of immutable and const:

> import std.stdio;
>
> void main()
> {
> auto p = Point(3);
> auto q = p.x;
> writeln(typeof(q).stringof);
> }
>
> struct Point
> {
> @property immutable long x;
> }

The type of q is immutable(long). But I need a mutable q. I 
found

two ways:

a) long q = p.x;
b) auto q = cast(long)p.x;

Either way I've to specify the type "long" which I dislike 
(here it's not a real burdon, but with more complicated types 
it might be). Is there a way, to make q mutable without having 
to write the type explicitly?


in this case you can just use:

auto q = cast()p.x;


or:

auto q = p.x + 0;


Re: getting rid of immutable (or const)

2019-09-05 Thread Daniel Kozak via Digitalmars-d-learn
On Thu, Sep 5, 2019 at 9:55 AM berni via Digitalmars-d-learn
 wrote:
>
> I still struggle with the concept of immutable and const:
>
> > import std.stdio;
> >
> > void main()
> > {
> > auto p = Point(3);
> > auto q = p.x;
> > writeln(typeof(q).stringof);
> > }
> >
> > struct Point
> > {
> > @property immutable long x;
> > }
>
> The type of q is immutable(long). But I need a mutable q. I found
> two ways:
>
> a) long q = p.x;
> b) auto q = cast(long)p.x;
>
> Either way I've to specify the type "long" which I dislike (here
> it's not a real burdon, but with more complicated types it might
> be). Is there a way, to make q mutable without having to write
> the type explicitly?

in this case you can just use:

auto q = cast()p.x;


getting rid of immutable (or const)

2019-09-05 Thread berni via Digitalmars-d-learn

I still struggle with the concept of immutable and const:


import std.stdio;

void main()
{
auto p = Point(3);
auto q = p.x;
writeln(typeof(q).stringof);
}

struct Point
{
@property immutable long x;
}


The type of q is immutable(long). But I need a mutable q. I found 
two ways:


a) long q = p.x;
b) auto q = cast(long)p.x;

Either way I've to specify the type "long" which I dislike (here 
it's not a real burdon, but with more complicated types it might 
be). Is there a way, to make q mutable without having to write 
the type explicitly?