digitalmars.D.learn - opCmp with structs
- Alex (21/21) Nov 06 2015 I'm sure I'm doing a silly mistake somewhere, but why this
- Alex (2/2) Nov 06 2015 Ok... the question is not silly any more...
- BBaz (3/5) Nov 06 2015 sort() fails because in the template constraint
- BBaz (34/36) Nov 06 2015 sorry, again a forum bug that stripped my answer:
- =?UTF-8?Q?Ali_=c3=87ehreli?= (8/26) Nov 06 2015 Continuing from your hint: So, opCmp works but it is sort() that cannot
- Alex (8/15) Nov 07 2015 So my general question is: why immutable variables shouldn't be
- Mike Parker (19/21) Nov 07 2015 To be pedantic, sort isn't actually moving anything. It's
- Alex (3/12) Nov 07 2015 Yeah... and I'm in the acceptance phase now ;) Do you have a
- Alex (14/14) Nov 07 2015 Found something useful, here:
- Alex (15/15) Nov 07 2015 Ok... found the solution. The technical at least.
- anonymous (2/11) Nov 07 2015 Wat. It even compiles with @safe. That's not good.
- anonymous (3/4) Nov 10 2015 Filed an issue:
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); }
Nov 06 2015
Ok... the question is not silly any more... without 'immutable' it works. So, what am I missing?
Nov 06 2015
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
Nov 06 2015
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.
Nov 06 2015
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? ;)
Nov 07 2015
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); } ---
Nov 07 2015
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...
Nov 07 2015
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
Nov 06 2015
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?
Nov 07 2015
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.
Nov 07 2015
On Saturday, 7 November 2015 at 14:36:25 UTC, Mike Parker wrote:Yeah... and I'm in the acceptance phase now ;) Do you have a hint, how this approach could be like?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.
Nov 07 2015
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?
Nov 07 2015
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!
Nov 07 2015
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.
Nov 07 2015
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
Nov 10 2015