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
}

Reply via email to