Thread overview |
---|
November 06, 2015 opCmp with structs | ||||
---|---|---|---|---|
| ||||
I'm sure I'm doing a silly mistake somewhere, but why this doesn't work? import std.stdio; import std.algorithm; struct ku { immutable int id; alias id this; this(int i) { id = i; } int opCmp(ref const ku rhs) const {return id - rhs.id; } } void main() { ku[] tt = [ku(2), ku(1)]; sort(tt); } |
November 06, 2015 Re: opCmp with structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Alex | Ok... the question is not silly any more... without 'immutable' it works. So, what am I missing? |
November 07, 2015 Re: opCmp with structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Alex | On 11/06/2015 02:54 PM, Alex wrote: > I'm sure I'm doing a silly mistake somewhere, but why this doesn't work? > import std.stdio; > import std.algorithm; > > struct ku > { > immutable int id; > alias id this; > > this(int i) > { > id = i; > } > > int opCmp(ref const ku rhs) const {return id - rhs.id; } > } > > void main() > { > ku[] tt = [ku(2), ku(1)]; > sort(tt); > } Continuing from your hint: So, opCmp works but it is sort() that cannot move objects of ku around because of that immutable variable. There may be references to ku objects or its id members and those references may be depending on the immutability of that member. const and immutable members effectively make objects unassignable. (const part is the same in C++.) Ali |
November 07, 2015 Re: opCmp with structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Alex | On Friday, 6 November 2015 at 22:55:15 UTC, Alex wrote:
> Ok... the question is not silly any more...
> without 'immutable' it works. So, what am I missing?
sort() fails because in the template constraint `hasAssignableElements
|
November 07, 2015 Re: opCmp with structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Alex | On Friday, 6 November 2015 at 22:55:15 UTC, Alex wrote:
> Ok... the question is not silly any more...
> without 'immutable' it works. So, what am I missing?
sorry, again a forum bug that stripped my answer:
sort() fails because in the template constraint `hasAssignableElements` fails.
hasAssignableElements fails because of this you cannot assign another value to a ku because the immutable member is already defined.
---
template hasAssignableElements(R)
{
enum bool hasAssignableElements = isInputRange!R && is(typeof(
(inout int = 0)
{
R r = R.init;
r.front = r.front;
static if (isBidirectionalRange!R) r.back = r.front;
static if (isRandomAccessRange!R) r[0] = r.front;
}));
}
---
more especially this is 'r.front = r.front;' that doesn't pass:
---
import std.range;
struct ku
{
immutable int id;
}
void main()
{
ku[] tt;
tt.front = tt.front;
}
---
so yeah, it cant work if id is immutable.
|
November 07, 2015 Re: opCmp with structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to BBaz | Ok, ok... I see the direction, but I still miss something: From the point of view of "Programming in D", chapter 33.3, "Immutability of the slice vs the elements": I don't want to have an immutable slice but immutable elements. And your answers imply that sorting not only modify the slice itself but also mutate the elements. This is a little bit strange, in my opinion, as sorting modifies only relationships between the sorted elements not the elements itself. At least in my head, at least for the moment :) A test says the same thing: void main() { immutable int[] immSlice = [2, 1]; sort(immSlice); } and void main() { immutable(int)[] immSlice = [2, 1]; sort(immSlice); } both give errors: Error: template std.algorithm.sorting.sort cannot deduce function from argument types !()(immutable(int[])) and Error: template std.algorithm.sorting.sort cannot deduce function from argument types !()(immutable(int)[]) respectively. So the question remains, how to sort? Do you think removing the immutable property from an id is the semantically right way? Or do you have a hint, maybe something like, a dup copy with removing immutability and returning a new, sorted copy? If you think the latter is the way to choose, how is the syntax there? ;) |
November 07, 2015 Re: opCmp with structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Alex | On Saturday, 7 November 2015 at 10:15:25 UTC, Alex wrote:
> So the question remains, how to sort? Do you think removing the immutable property from an id is the semantically right way? Or do you have a hint, maybe something like, a dup copy with removing immutability and returning a new, sorted copy? If you think the latter is the way to choose, how is the syntax there? ;)
This fails because in sort() a struct is considered as a value, so the instance are not moved, it looks like this() is called using the instance of another slot.
So to get rid of that use some pointer to struct, here when sort() will have to move it'll move the reference:
---
import std.stdio;
import std.algorithm;
struct ku
{
immutable int id;
alias id this;
this(int i)
{
id = i;
}
int opCmp(ref const ku rhs) const {return id - rhs.id; }
}
void main()
{
ku*[] tt = [new ku(2),new ku(1)];
sort(tt);
}
---
|
November 07, 2015 Re: opCmp with structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to BBaz | On Saturday, 7 November 2015 at 10:24:03 UTC, BBaz wrote:
> void main()
> {
> ku*[] tt = [new ku(2),new ku(1)];
> sort(tt);
> }
Don't really like this ;) not because
writeln(tt);
doesn't work any more, but because I have to think about where to use pointers and where not...
|
November 07, 2015 Re: opCmp with structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Saturday, 7 November 2015 at 00:19:56 UTC, Ali Çehreli wrote: > Continuing from your hint: So, opCmp works but it is sort() that cannot move objects of ku around because of that immutable variable. So my general question is: why immutable variables shouldn't be able to be moved (inside an array)? > There may be references to ku objects or its id members and those references may be depending on the immutability of that member. const and immutable members effectively make objects unassignable. (const part is the same in C++.) And this is also something unexpected: yes, there may be such references and they should stay valid of course. But why shouldn't be a concrete collection of such references be sortable? Why this should affect other references to the individual 'ku' objects? |
November 07, 2015 Re: opCmp with structs | ||||
---|---|---|---|---|
| ||||
Posted in reply to Alex | On Saturday, 7 November 2015 at 11:48:56 UTC, Alex wrote:
>
> So my general question is: why immutable variables shouldn't be able to be moved (inside an array)?
>
To be pedantic, sort isn't actually moving anything. It's reassigning elements, i.e. a[1] = a[2]. The immutable member makes it illegal to assign one instance of ku to another:
void main() {
ku k = ku(1);
k = ku(2);
}
That's why it's failing. It's actually possible to use move one instance into another, though:
void main() {
import std.algorithm : move;
ku k1 = ku(1);
ku k2 = ku(2);
k2.move(k1);
assert(k1.id == 2);
}
But sort doesn't work that way. You'll need to take a different approach to sort an array of ku.
|
Copyright © 1999-2021 by the D Language Foundation