www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Sorting a zipped range

reply "Ben Jones" <fake fake.fake> writes:
One of the cool features of D that I've attempted before in c++ 
is to sort a set of ranges in lockstep like (not syntactically 
correct):

auto a = [5,4,3,2,1]
auto b = [1,2,3,4,5]


auto sorter = (Tuple x, Tuple y) => x.get(0) < y.get(0);
sort!sorter(zip(a,b));

-> a = [1,2,3,4,5], b = [5,4,3,2,1]

In c++ this seems basically impossible to do correctly with 
std::sort because it seems impossible to make a random access 
iterator type that can be returned from zip() that has the 
correct semantics (see here: 
http://stackoverflow.com/questions/13840998/sorting-zipped-locked-containers-in-c-using-boost-or-the-stl)

My question is:  which features of the D range abstraction allow 
zip to work the way we expect?  What C++isms were left behind to 
make this work?
Feb 27 2014
next sibling parent reply "Tobias Pankrath" <tobias pankrath.net> writes:
On Thursday, 27 February 2014 at 21:09:45 UTC, Ben Jones wrote:

 My question is:  which features of the D range abstraction 
 allow zip to work the way we expect?  What C++isms were left 
 behind to make this work?
Many items in std.algorithm / std.range make use of static if to provide the most capable return types. I.e. if you zip to RA ranges than zip will return a random access range, too. See https://github.com/D-Programming-Language/phobos/blob/master/std/range.d#L4988
Feb 27 2014
parent "Ben Jones" <fake fake.fake> writes:
On Thursday, 27 February 2014 at 21:24:20 UTC, Tobias Pankrath 
wrote:
 On Thursday, 27 February 2014 at 21:09:45 UTC, Ben Jones wrote:

 My question is:  which features of the D range abstraction 
 allow zip to work the way we expect?  What C++isms were left 
 behind to make this work?
Many items in std.algorithm / std.range make use of static if to provide the most capable return types. I.e. if you zip to RA ranges than zip will return a random access range, too. See https://github.com/D-Programming-Language/phobos/blob/master/std/range.d#L4988
That can be done in C++ too (albeit less elgantly) with tag dispatch or enable if, or whatever. The big issue I ran into was dealing with the semantics of iterator dereferencing. I'm not sure anyone has come up with a way to define an iterator whose dereference operator returns a reference type when dealing with a zipped range in C++. It seems that somehow D's range abstraction avoids that issues somehow, but I don't quite understand how.
Feb 27 2014
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 02/27/2014 10:09 PM, Ben Jones wrote:
 My question is:  which features of the D range abstraction allow zip to
 work the way we expect?
Assignable elements of a range do not need to be addressable.
 What C++isms were left behind to make this work?
In C++, iterators should implement operator-> which must return a pointer to data, and unary operator*, which should return a reference if it is to be assignable. This makes the iterator abstraction less flexible. I.e. it is a consequence of - desire to use pointer-like syntax for iterators - weak support for hooking into the corresponding syntactic constructs Phobos eg. allows retrieval of and assignment to a range's front element to be implemented in distinct methods that can execute arbitrary code. Zip uses such facilities to distribute assignments to its range elements back to each source range.
Feb 27 2014
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Ben Jones:

 auto sorter = (Tuple x, Tuple y) => x.get(0) < y.get(0);
 sort!sorter(zip(a,b));
You can write that as (untested): zip(a, b).sort!((x, y) => x[0] < y[0]); Or even just: a.zip(b).sort!q{ a[0] < b[0] }; Bye, bearophile
Feb 27 2014