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
}