I wrote a function that accepts input ranges, and I get compile errors when passing an array
pineapple via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Fri May 27 07:54:30 PDT 2016
I'm writing my own map function modeled after the one in phobos.
(because I feel like it, that's why. good learning experience.)
I've encountered one remarkable difference: The phobos function
accepts arrays and mine does not. I understand why - I'm calling
methods that arrays don't have - but what I don't understand is
why the phobos function _does_ work. I haven't been able to find
what in the phobos code accounts for iterables that aren't ranges.
What am I missing?
enum canMap(T) = isInputRange!(Unqual!T);
auto map(alias func, Range)(Range range) if(canMap!Range){
return Mapping!(func, Range)(range);
}
struct Mapping(alias func, Range) if(canMap!Range){
alias URange = Unqual!Range;
Range input;
this(URange input){
this.input = input;
}
void popFront(){
this.input.popFront();
}
@property auto ref front(){
return func(this.input.front);
}
static if(isBidirectionalRange!URange){
@property auto ref back(){
return func(this.input.back);
}
void popBack(){
this.input.popBack();
}
}
static if(isInfinite!URange){
enum bool empty = false;
}else{
@property bool empty(){
return this.input.empty;
}
}
static if(isRandomAccessRange!URange){
static if(is(typeof(URange.opIndex) == function)){
alias Index = Parameters!(URange.opIndex)[0];
}else{
alias Index = size_t;
}
auto ref opIndex(Index index){
return func(this.input[index]);
}
}
static if(is(typeof(URange.opDollar))){
alias opDollar = URange.opDollar;
}
static if(hasLength!URange){
@property auto length(){
return this.input.length;
}
}
static if(hasSlicing!URange){
static if(is(typeof(URange.opIndex) == function)){
alias SliceIndex = Parameters!(URange.opIndex)[0];
}else{
alias SliceIndex = size_t;
}
auto opSlice(SliceIndex low, SliceIndex high){
return typeof(this)(this.input[low .. high]);
}
}
static if(isForwardRange!URange){
@property auto save(){
return typeof(this)(this.input.save);
}
}
}
version(unittest) import mach.error.unit;
unittest{
import std.stdio;
//import std.algorithm : map; // Works with this
// no property 'popFront', etc for type 'int[]'
writeln(
[1, 2, 3].map!((item) => (item * item))
);
}
Tangentially related question - Why does phobos use
isInputRange!(Unqual!T) instead of just isInputRange!T? What's
the functional difference here?
More information about the Digitalmars-d-learn
mailing list