Re: sortOn: sorts range of aggregates by member name(s)
Andrei Alexandrescu: Sadly things don't work that way - e.g. Phobos1 took a bunch of string functions from Ruby and Python, to no notable effect. If you port Python code to D (and this is something I do almost every day) the Phobos string functions help making the porting simpler. Bye, bearophile
Re: sortOn: sorts range of aggregates by member name(s)
On 11/10/14 12:56 AM, bearophile wrote: Andrei Alexandrescu: Sadly things don't work that way - e.g. Phobos1 took a bunch of string functions from Ruby and Python, to no notable effect. If you port Python code to D (and this is something I do almost every day) the Phobos string functions help making the porting simpler. Bye, bearophile Good to know, thanks! -- Andrei
Re: sortOn: sorts range of aggregates by member name(s)
On Monday, 10 November 2014 at 03:38:49 UTC, Andrei Alexandrescu wrote: That's a better approach, thanks. A few compelling examples would help. Andrei One more thing. How should reverse sorting be handled in elegant way? Like this https://github.com/nordlow/justd/blob/master/sort_ex.d#L57 or via some other clever solution I haven't thought about?
Re: sortOn: sorts range of aggregates by member name(s)
On Monday, 10 November 2014 at 19:58:32 UTC, Nordlöw wrote: On Monday, 10 November 2014 at 03:38:49 UTC, Andrei Alexandrescu wrote: That's a better approach, thanks. A few compelling examples would help. Andrei One more thing. How should reverse sorting be handled in elegant way? Like this https://github.com/nordlow/justd/blob/master/sort_ex.d#L57 or via some other clever solution I haven't thought about? By chaining it with std.range.retro? But this will of course be lazy, and will lose the information that the range is sorted. Maybe there doesn't need to be a special facility for that, if it's allowed to specify arbitrary expressions? container.sortBy!(a = a.intMember)// ascending container.sortBy!(a = -a.intMember)// descending Or shorter (the expression will be mixed in): container.sortBy! intMember; // ascending container.sortBy!-intMember; // descending
Re: sortOn: sorts range of aggregates by member name(s)
On 11/10/14 11:58 AM, Nordlöw wrote: On Monday, 10 November 2014 at 03:38:49 UTC, Andrei Alexandrescu wrote: That's a better approach, thanks. A few compelling examples would help. Andrei One more thing. How should reverse sorting be handled in elegant way? Like this https://github.com/nordlow/justd/blob/master/sort_ex.d#L57 or via some other clever solution I haven't thought about? For most numeric cases having the caller negate the key should suffice. For string types you'd need a separate function or fall back to classic sort. This, too, doesn't bode well for the power/weight ratio of sortBy. -- Andrei
Re: sortOn: sorts range of aggregates by member name(s)
On Monday, 10 November 2014 at 03:38:49 UTC, Andrei Alexandrescu wrote: On 11/9/14 4:49 AM, Nordlöw wrote: On Sunday, 9 November 2014 at 08:12:37 UTC, Andrei Alexandrescu wrote: sortBy!(expr) is equivalent with sort!(expr_a expr_b) so there's no additional power to it. However, it does make some sorting criteria easier to write. A while ago I took a related diff pretty far but in the end decided to discard it because it didn't add sufficient value. What do you mean by sufficient value? It seemed to me just another way of doing the same things. Ruby has sort_by. I believe D would when possible should be a superset of the union of powers available in other languages to maximize the ease of porting code *to* D and the pleasure for programmers to switch to D. Sadly things don't work that way - e.g. Phobos1 took a bunch of string functions from Ruby and Python, to no notable effect. I'll try to make this elegant and useful and use it myself for a while. If it works for me I'll do a PR still. Ok? That's a better approach, thanks. A few compelling examples would help. A positive point about it would be that it's more intuitive to read, especially with long names or complex expressions. // sort vectors by length container.sortBy!x*x + y*y; // vs. container.sort!((a,b) = a.x*a.x + a.y*a.y b.x*b.x + b.y*b.y);
Re: sortOn: sorts range of aggregates by member name(s)
On 11/5/14 12:18 PM, Marc =?UTF-8?B?U2Now7x0eiI=?= schue...@gmx.net wrote: On Wednesday, 5 November 2014 at 00:34:54 UTC, Meta wrote: On Wednesday, 5 November 2014 at 00:32:32 UTC, Nordlöw wrote: Has there been any proposals to add a sort-wrapper, say sortBy, in cases such as struct X { double x, y, z; } auto r = new X[3]; used as r.sortBy!(x, y) sorting r by value of x then y. If not and anybody is interest I could write one and make PR in std.algorithm. I think you're looking for multiSort. http://dlang.org/phobos/std_algorithm.html#.multiSort That's not the same, it requires to specify a comparison function. Nordlöw wants to specify an attribute. This could also be an arbitrary expression, of course: r.sortBy!x*x + y*y + z*z The above could be implemented using `with` and `std.functional.unaryFun`. Alternatively, a lambda could be used: r.sortBy!(a = a.norm); sortBy!(expr) is equivalent with sort!(expr_a expr_b) so there's no additional power to it. However, it does make some sorting criteria easier to write. A while ago I took a related diff pretty far but in the end decided to discard it because it didn't add sufficient value. Andrei
Re: sortOn: sorts range of aggregates by member name(s)
On Sunday, 9 November 2014 at 08:12:37 UTC, Andrei Alexandrescu wrote: sortBy!(expr) is equivalent with sort!(expr_a expr_b) so there's no additional power to it. However, it does make some sorting criteria easier to write. A while ago I took a related diff pretty far but in the end decided to discard it because it didn't add sufficient value. What do you mean by sufficient value? Ruby has sort_by. I believe D would when possible should be a superset of the union of powers available in other languages to maximize the ease of porting code *to* D and the pleasure for programmers to switch to D. I'll try to make this elegant and useful and use it myself for a while. If it works for me I'll do a PR still. Ok?
Re: sortOn: sorts range of aggregates by member name(s)
Nordlöw: What do you mean by sufficient value? Every thing you add to Phobos std.algorithmstd.range increases the amount of things D programmers have to understand and keep in _active memory_. So you have to balance the desire to add specialized functionality with the desire to keep that complexity low. And I think adding sortBy isn't a good idea. If you really want to do something like that, I think it's better to add something more like Python operator.attrgetter (https://docs.python.org/2/library/operator.html ), that can be used with the standard sort: items.sort!(fieldGetter(field1, field2)); Bye, bearophile
Re: sortOn: sorts range of aggregates by member name(s)
On 11/9/14 4:49 AM, Nordlöw wrote: On Sunday, 9 November 2014 at 08:12:37 UTC, Andrei Alexandrescu wrote: sortBy!(expr) is equivalent with sort!(expr_a expr_b) so there's no additional power to it. However, it does make some sorting criteria easier to write. A while ago I took a related diff pretty far but in the end decided to discard it because it didn't add sufficient value. What do you mean by sufficient value? It seemed to me just another way of doing the same things. Ruby has sort_by. I believe D would when possible should be a superset of the union of powers available in other languages to maximize the ease of porting code *to* D and the pleasure for programmers to switch to D. Sadly things don't work that way - e.g. Phobos1 took a bunch of string functions from Ruby and Python, to no notable effect. I'll try to make this elegant and useful and use it myself for a while. If it works for me I'll do a PR still. Ok? That's a better approach, thanks. A few compelling examples would help. Andrei
Re: sortOn: sorts range of aggregates by member name(s)
On Wednesday, 5 November 2014 at 21:29:20 UTC, Marc Schütz wrote: Again untested: private alias makePredicate(alias xtr) = (a, b) = (extractorFun!xtr(a) extractorFun!xtr(b)); This errors as sort_ex.d(35,43): Error: basic type expected, not ( sort_ex.d(35,43): Error: function declaration without return type. (Note that constructors are always named 'this') sort_ex.d(35,50): Error: semicolon expected to close alias declaration sort_ex.d(35,50): Error: Declaration expected, not '=' auto sortBy(extractors..., R)(R r) { alias preds = staticMap!(makePredicate, extractors); return r.sort!preds; } and this as sort_ex.d(37,6): Error: template sort_ex.sortBy(xtors..., R)(R r) template tuple parameter must be last one
Re: sortOn: sorts range of aggregates by member name(s)
On Thursday, 6 November 2014 at 09:13:07 UTC, Nordlöw wrote: On Wednesday, 5 November 2014 at 21:29:20 UTC, Marc Schütz wrote: Again untested: private alias makePredicate(alias xtr) = (a, b) = (extractorFun!xtr(a) extractorFun!xtr(b)); This errors as sort_ex.d(35,43): Error: basic type expected, not ( sort_ex.d(35,43): Error: function declaration without return type. (Note that constructors are always named 'this') sort_ex.d(35,50): Error: semicolon expected to close alias declaration sort_ex.d(35,50): Error: Declaration expected, not '=' It probably needs to be spelled out as function/delegate literal (sorry, don't have much time now). auto sortBy(extractors..., R)(R r) { alias preds = staticMap!(makePredicate, extractors); return r.sort!preds; } and this as sort_ex.d(37,6): Error: template sort_ex.sortBy(xtors..., R)(R r) template tuple parameter must be last one Try nesting the templates, then the tuple can come first: template sortBy(extractors...) { auto sortBy(R)(R r) { // ... } } This should then be usable as `sortBy!(x, y)(range)`.
Re: sortOn: sorts range of aggregates by member name(s)
On Wednesday, 5 November 2014 at 00:34:54 UTC, Meta wrote: On Wednesday, 5 November 2014 at 00:32:32 UTC, Nordlöw wrote: Has there been any proposals to add a sort-wrapper, say sortBy, in cases such as struct X { double x, y, z; } auto r = new X[3]; used as r.sortBy!(x, y) sorting r by value of x then y. If not and anybody is interest I could write one and make PR in std.algorithm. I think you're looking for multiSort. http://dlang.org/phobos/std_algorithm.html#.multiSort That's not the same, it requires to specify a comparison function. Nordlöw wants to specify an attribute. This could also be an arbitrary expression, of course: r.sortBy!x*x + y*y + z*z The above could be implemented using `with` and `std.functional.unaryFun`. Alternatively, a lambda could be used: r.sortBy!(a = a.norm);
Re: sortOn: sorts range of aggregates by member name(s)
On Wednesday, 5 November 2014 at 11:18:56 UTC, Marc Schütz wrote: This could also be an arbitrary expression, of course: r.sortBy!x*x + y*y + z*z The above could be implemented using `with` and `std.functional.unaryFun`. Alternatively, a lambda could be used: r.sortBy!(a = a.norm); Ok. Great. What do you think about the name sortBy?
Re: sortOn: sorts range of aggregates by member name(s)
On Wednesday, 5 November 2014 at 14:07:10 UTC, Nordlöw wrote: On Wednesday, 5 November 2014 at 11:18:56 UTC, Marc Schütz wrote: This could also be an arbitrary expression, of course: r.sortBy!x*x + y*y + z*z The above could be implemented using `with` and `std.functional.unaryFun`. Alternatively, a lambda could be used: r.sortBy!(a = a.norm); Ok. Great. What do you think about the name sortBy? It's intuitive and concise. Plus, Ruby uses `sort` and `sort_by` for the same functionality, exactly in parallel, so it will be familiar to many users.
Re: sortOn: sorts range of aggregates by member name(s)
Marc Schütz: r.sortBy!(a = a.norm); r.schwartzSort!(a = a.norm); Bye, bearophile
Re: sortOn: sorts range of aggregates by member name(s)
On Wednesday, 5 November 2014 at 14:52:38 UTC, bearophile wrote: Marc Schütz: r.sortBy!(a = a.norm); r.schwartzSort!(a = a.norm); Bye, bearophile Ok, but this doesn't support multi-sorting, right?
Re: sortOn: sorts range of aggregates by member name(s)
Nordlöw: Ok, but this doesn't support multi-sorting, right? If performance is not a top priority, you can use a tuple: r.schwartzSort!(x = tuple(x.a, x.b, x.c)); Bye, bearophile
Re: sortOn: sorts range of aggregates by member name(s)
On Wednesday, 5 November 2014 at 14:36:11 UTC, Marc Schütz wrote: It's intuitive and concise. Plus, Ruby uses `sort` and `sort_by` for the same functionality, exactly in parallel, so it will be familiar to many users. Here's my first working but primitive version. https://github.com/nordlow/justd/blob/master/sort_ex.d#L15 How do I extend it to support - variadic number of extractors - sortBy(x) ?
Re: sortOn: sorts range of aggregates by member name(s)
On Wednesday, 5 November 2014 at 16:07:40 UTC, Nordlöw wrote: On Wednesday, 5 November 2014 at 14:36:11 UTC, Marc Schütz wrote: It's intuitive and concise. Plus, Ruby uses `sort` and `sort_by` for the same functionality, exactly in parallel, so it will be familiar to many users. Here's my first working but primitive version. https://github.com/nordlow/justd/blob/master/sort_ex.d#L15 How do I extend it to support - variadic number of extractors - sortBy(x) My idea was something along these lines (untested): template extractorFun(alias extractor) { static if(is(typeof(extractor) : string)) { auto ref extractorFun(T)(auto ref T a) { mixin(with(a) { return ~ extractor ~ ; }); } } else { alias extractorFun = extractor; } } alias fn = extractorFun!extractor; r.sort!((a, b) = (fn(a) fn(b)));
Re: sortOn: sorts range of aggregates by member name(s)
On Wednesday, 5 November 2014 at 16:54:38 UTC, Marc Schütz wrote: My idea was something along these lines (untested): template extractorFun(alias extractor) { static if(is(typeof(extractor) : string)) { auto ref extractorFun(T)(auto ref T a) { mixin(with(a) { return ~ extractor ~ ; }); } } else { alias extractorFun = extractor; } } alias fn = extractorFun!extractor; r.sort!((a, b) = (fn(a) fn(b))); Thanks, I'll use this! Still, is it even possible to extend extractor to become variadic or do I have to write a number of explicit overloads 1: void sortBy(alias xtr, R)(R r) 2: void sortBy(alias xtrA, alias xtrB, R)(R r) 3: void sortBy(alias xtrA, alias xtrB, alias xtrC, R)(R r) etc ?
Re: sortOn: sorts range of aggregates by member name(s)
On Wednesday, 5 November 2014 at 20:50:00 UTC, Nordlöw wrote: On Wednesday, 5 November 2014 at 16:54:38 UTC, Marc Schütz wrote: My idea was something along these lines (untested): template extractorFun(alias extractor) { static if(is(typeof(extractor) : string)) { auto ref extractorFun(T)(auto ref T a) { mixin(with(a) { return ~ extractor ~ ; }); } } else { alias extractorFun = extractor; } } alias fn = extractorFun!extractor; r.sort!((a, b) = (fn(a) fn(b))); Thanks, I'll use this! Still, is it even possible to extend extractor to become variadic or do I have to write a number of explicit overloads 1: void sortBy(alias xtr, R)(R r) 2: void sortBy(alias xtrA, alias xtrB, R)(R r) 3: void sortBy(alias xtrA, alias xtrB, alias xtrC, R)(R r) etc ? Again untested: private alias makePredicate(alias xtr) = (a, b) = (extractorFun!xtr(a) extractorFun!xtr(b)); auto sortBy(extractors..., R)(R r) { alias preds = staticMap!(makePredicate, extractors); return r.sort!preds; } (Variadic template parameters also accept aliases.)
Re: sortOn: sorts range of aggregates by member name(s)
On Wednesday, 5 November 2014 at 16:54:38 UTC, Marc Schütz wrote: On Wednesday, 5 November 2014 at 16:07:40 UTC, Nordlöw wrote: On Wednesday, 5 November 2014 at 14:36:11 UTC, Marc Schütz wrote: It's intuitive and concise. Plus, Ruby uses `sort` and `sort_by` for the same functionality, exactly in parallel, so it will be familiar to many users. Here's my first working but primitive version. https://github.com/nordlow/justd/blob/master/sort_ex.d#L15 How do I extend it to support - variadic number of extractors - sortBy(x) My idea was something along these lines (untested): template extractorFun(alias extractor) { static if(is(typeof(extractor) : string)) { auto ref extractorFun(T)(auto ref T a) { mixin(with(a) { return ~ extractor ~ ; }); } } else { alias extractorFun = extractor; } } alias fn = extractorFun!extractor; r.sort!((a, b) = (fn(a) fn(b))); Works! Thanks! One thing: I tried to add support for integer based member indexing via tupleof at https://github.com/nordlow/justd/blob/master/sort_ex.d#L21 but it errors as sort_ex.d(42,46): Error: function expected before (), not 0 of type int sort_ex.d(43,46): Error: function expected before (), not 0 of type int sort_ex.d(42,6):instantiated from here: sort!((a, b) = extractorFun!extractor(a) extractorFun!extractor(b), cast(SwapStrategy)0, X[]) sort_ex.d(80,6):instantiated from here: sortBy!(0, X[]) /home/per/opt/x86_64-unknown-linux-gnu/dmd/linux/bin64/src/phobos/std/algorithm.d(10266,9): Error: static assert Invalid predicate passed to sort: __lambda2 sort_ex.d(42,6):instantiated from here: sort!((a, b) = extractorFun!extractor(a) extractorFun!extractor(b), cast(SwapStrategy)0, X[]) sort_ex.d(80,6):instantiated from here: sortBy!(0, X[]) when I uncomment the last three tests. What's wrong?
Re: sortOn: sorts range of aggregates by member name(s)
On Wednesday, 5 November 2014 at 23:40:23 UTC, Nordlöw wrote: when I uncomment the last three tests. What's wrong? Solved it :)
Re: sortOn: sorts range of aggregates by member name(s)
On Wednesday, 5 November 2014 at 00:32:32 UTC, Nordlöw wrote: Has there been any proposals to add a sort-wrapper, say sortBy, in cases such as struct X { double x, y, z; } auto r = new X[3]; used as r.sortBy!(x, y) sorting r by value of x then y. If not and anybody is interest I could write one and make PR in std.algorithm. I think you're looking for multiSort. http://dlang.org/phobos/std_algorithm.html#.multiSort