November 05, 2014 Re: sortOn: sorts range of aggregates by member name(s) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Marc Schütz | 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
?
| |||
November 05, 2014 Re: sortOn: sorts range of aggregates by member name(s) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Nordlöw | 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.)
| |||
November 05, 2014 Re: sortOn: sorts range of aggregates by member name(s) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Marc Schütz | 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? | |||
November 06, 2014 Re: sortOn: sorts range of aggregates by member name(s) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Nordlöw | 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 :)
| |||
November 06, 2014 Re: sortOn: sorts range of aggregates by member name(s) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Marc Schütz | 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 | |||
November 06, 2014 Re: sortOn: sorts range of aggregates by member name(s) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Nordlöw | 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)`. | |||
November 09, 2014 Re: sortOn: sorts range of aggregates by member name(s) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Marc Schütz | On 11/5/14 12:18 PM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm@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
| |||
November 09, 2014 Re: sortOn: sorts range of aggregates by member name(s) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | 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?
| |||
November 09, 2014 Re: sortOn: sorts range of aggregates by member name(s) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Nordlöw | Nordlöw: > What do you mean by sufficient value? Every thing you add to Phobos std.algorithm&std.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 | |||
November 10, 2014 Re: sortOn: sorts range of aggregates by member name(s) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Nordlöw | 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 | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply