Coercing ranges to the same type

Jesse Phillips via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Jul 7 21:24:07 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.

I'd say, try to move 'recurse' into a compile time variable, if 
you need it runtime, move it up a layer:

import std.file;
import std.range;
import std.algorithm;

void main(string[] args) {
     import std.stdio;
     auto recurse = true;
     if(recurse)
         args.getFiles.chain(recurseForFiles(args[])).writeln;
     else
         args.getFiles.writeln;
}

auto getFiles(string[] paths)
{
     return paths.filter!(p => p.isFile);
}

auto recurseForFiles(string[] paths) {
     return paths
         .filter!(p => p.isDir)
         .map!(p => dirEntries(p, SpanMode.depth, false))
         .joiner
         .filter!(p => p.isFile)
         .map!(de => de.name); // back to strings
}



More information about the Digitalmars-d-learn mailing list