Re: opCmp with structs
On 07.11.2015 16:59, anonymous wrote: Wat. It even compiles with @safe. That's not good. Filed an issue: https://issues.dlang.org/show_bug.cgi?id=15315
Re: opCmp with structs
Ok... found the solution. The technical at least. import std.algorithm; import std.range; void main(){ ku[] tt = [ku(2), ku(1)]; //writeln(tt); auto index3 = new size_t[tt.length]; makeIndex!("a.id < b.id")(tt, index3); auto ind = indexed(tt, index3); //writeln(ind); } This yield in 'ind' the array of 'tt', ordered in the expected way. So, the remaining open questions are just ideologic now... Thanks for helping and commenting!
Re: opCmp with structs
Found something useful, here: http://dlang.org/phobos/std_algorithm_sorting.html#makeIndex with that I can achieve the following void main(){ ku[] tt = [ku(2), ku(1)]; //writeln(tt); auto index3 = new size_t[tt.length]; makeIndex!("a.id < b.id")(tt, index3); //writeln(index3); } so my index3 contains the right permutation of the tt array. What I still need is the possibility to take the values of the tt array in the order of the generated index. Can somebody give a hint how to achieve this?
Re: opCmp with structs
On 07.11.2015 15:36, Mike Parker wrote: 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); } Wat. It even compiles with @safe. That's not good.
Re: opCmp with structs
On Saturday, 7 November 2015 at 14:36:25 UTC, Mike Parker 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: But sort doesn't work that way. You'll need to take a different approach to sort an array of ku. Yeah... and I'm in the acceptance phase now ;) Do you have a hint, how this approach could be like?
Re: opCmp with structs
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.
Re: opCmp with structs
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?
Re: opCmp with structs
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...
Re: opCmp with structs
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); } ---
Re: opCmp with structs
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? ;)
Re: opCmp with structs
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.
Re: opCmp with structs
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
Re: opCmp with structs
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
Re: opCmp with structs
Ok... the question is not silly any more... without 'immutable' it works. So, what am I missing?
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); }