Combining infinite ranges

bearophile bearophileHUGS at lycos.com
Wed Jun 2 17:24:43 PDT 2010


Andrei Alexandrescu:
> iota(n, n.max) is close. Well, it's not infinite, but cycle(iota(n, 
> n.max)) is. Probably a version using BigInt would be most sensible.


An enumerate() too can be useful (not much tested yet):


import std.range: isForwardRange, hasLength, isBidirectionalRange, ElementType;
import std.typecons: Tuple;
import std.array: front, back, empty, popFront, popBack;

/// ...
struct Enumerate(R) if (isForwardRange!R) {
    alias Tuple!(size_t, "index", ElementType!R, "item") TPair;
    R _range;
    size_t _index;
    static if (isBidirectionalRange!R && hasLength!R)
        immutable size_t _originalEnd;

    this(R input) {
        _range = input;
        static if (isBidirectionalRange!R && hasLength!R)
            _originalEnd = _range.length - 1;

    }

    /// Range primitive implementations.
    ref TPair front() {
        return TPair(_index, _range.front());
    }

    /// Ditto
    bool empty() {
        return _range.empty();
    }

    /// Ditto
    void popFront() {
        _range.popFront();
        _index++;
    }

    static if (isBidirectionalRange!R && hasLength!R) {
        /// Ditto
        ref TPair back() {
            return TPair(_originalEnd + _index, _range.back());
        }
    }

    static if (isBidirectionalRange!R && hasLength!R) {
        /// Ditto
        void popBack() {
            _range.popBack();
            _index--;
        }
    }

    static if (hasLength!R) {
        /// Ditto
        @property auto length() {
            return _range.length;
        }
    }
}

/// Ditto
Enumerate!R enumerate(R)(R input) if (isForwardRange!R) {
    return Enumerate!R(input);
}

import std.stdio: write, writeln;

void main() {
    string[] arr = ["y", "n", "y", "n", "y"];

    foreach (el; enumerate(arr))
        write(el, " ");
    writeln("\n");

    foreach_reverse (el; enumerate(arr))
        write(el, " ");
    writeln("\n");
}


I don't know if a reverse iteration on an enumerate can be useful.

-----------------------

I have used that to try to implement in D2 this Python code:

>>> arr = ["y", "n", "y", "n", "y"]
>>> [i for i,el in enumerate(arr) if el == "y"]
[0, 2, 4]


This is a basic D version, Appender not used:

import std.stdio: writeln;

void main() {
    // input data
    string[] arr = ["y", "n", "y", "n", "y"];

    // 
    int[] indexes;
    foreach (i, item; arr)
        if (item == "y")
            indexes ~= i;
    writeln(indexes);
    writeln();
}

-----------------------

This is a more functional quite bad-looking D2 version, that doesn't work (see http://d.puremagic.com/issues/show_bug.cgi?id=4264 ):

import std.stdio: writeln;
import std.algorithm: filter, array, map;

void main() {
    // input data
    string[] arr = ["y", "n", "y", "n", "y"];

    auto r1 = filter!((p){ return p.item == "y"; })(enumerate(arr));
    auto r2 = map!((p){ return p.index; })(r1);
    writeln(array(r2));
}

Bye,
bearophile


More information about the Digitalmars-d mailing list