higher-order funcs for ranges (with usual interface)
Lars T. Kyllingstad
public at kyllingen.NOSPAMnet
Wed Feb 2 05:18:07 PST 2011
On Wed, 02 Feb 2011 13:26:39 +0100, spir wrote:
> Hello,
>
> This bit of code for arrays:
>
> Out[] map (In,Out) (In[] input, Out delegate (In) f) {
> Out[] output = new Out[](input.length); foreach (i,item ; input)
> output [i] = f(item);
> return output;
> }
> unittest {
> char character (uint code) {return cast(char)code;} uint[] codes =
> [0x61,0x62,0x63];
> // functional style
> writeln(map(codes, &character)); // "abc" // OO style
> writeln(codes.map(&character)); // "abc"
> }
>
> How to write this for ranges? [...]
>
> For ranges, I'm looking for something similar to:
> Range!Out map (In,Out) (Range!In input, Out delegate (In) f) {...}
> Indeed, the compiler should understand that Range!T is a type id just
> like T[].
I don't think it's possible to do it exactly as you describe. I mean,
Range in that case can be anything, and you can't always return a range
of the same kind. Two possibilities are, you can do it eagerly,
Out[] map(Range, In, Out)(Range input, Out delegate(In) f)
if (isInputRange!Range && is(ElementType!Range : In))
{
...
}
or you can do it lazily by defining your own map range (untested):
struct Map(Range, In, Out)
if (isInputRange!Range && is(ElementType!Range : In)
{
Range input;
Out delegate(In) f;
@property bool empty() { return input.empty; }
// Inefficient, should cache front...
@property Out front() { return f(input.front); }
void popFront() { input.popFront(); }
}
Map!(Range, Out) map(Range, In, Out)(Range input, Out delegate(In) f)
if (isInputRange!R && is(ElementType!Range : In)
{
return typeof(return)(input, f);
}
-Lars
More information about the Digitalmars-d-learn
mailing list