Coercing ranges to the same type
Alex Parrill via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Mon Jul 6 14:35:51 PDT 2015
On Monday, 6 July 2015 at 19:46:51 UTC, Matt Kline wrote:
> Say I'm trying to expand an array of file and directory paths
> (such as ones given as command line args) into a range of file
> paths I can iterate over. A simplified example might be:
>
> auto getEntries(string[] paths, bool recursive)
> {
> auto files = paths.filter!(p => p.isFile);
>
> if (recursive) {
> auto expandedDirs = paths
> .filter!(p => p.isDir)
> .map!(p => dirEntries(p, SpanMode.depth, false))
> .joiner
> .map!(de => de.name); // back to strings
>
> return chain(files, expandedDirs);
> }
> else {
> return files;
> }
> }
>
> Even though both return statements return a range of strings,
> this doesn't compile because the result of `chain` is a
> different type than the result of `filter`. Is there some
> generic range I could coerce both ranges to in order to have
> the same return type and make this work? .array is a
> non-starter since it throws out the ranges' laziness.
They aren't actually the same types; one is a
`FilterRange!(string[])`; the other a `ChainRange!(string[],
MapRange!(...))`. Since they're structs, there's no runtime
polymorphism.
You can either make `recursive` a template argument (`auto
getEntries(bool recursive)(string[] paths)`) with `static if` if
you know at compile time when to recurse or not, or use a class
wrapper in std.range.interface [1].
[1]: http://dlang.org/phobos/std_range_interfaces.html
More information about the Digitalmars-d-learn
mailing list