Example:

import std.stdio;
import std.algorithm;
import std.path;
import std.file;
import std.exception;
import std.getopt;
import std.array;
import std.range;

auto algo(string fileName, string[] dirs, string[] extensions)
{
    return dirs.filter!(delegate(dir) {
        bool ok;
        collectException(dir.isDir, ok);
        return ok;
    }).map!(dir => extensions
        .map!(delegate(ext) {
            string path = buildPath(dir, fileName ~ ext);
            writefln("Map: %s", path);
            return path;
        }).filter!(delegate(filePath) {
            bool ok;
            writefln("Check: %s", filePath);
            collectException(filePath.isFile, ok);
            return ok;
        })
    ).joiner;
}

void main(string[] args)
{
    string fileName;
    string extensionsStr;
    getopt(args,
"fileName", "file name to search without extension", &fileName, "extensions", "list of extensions separated by ':'", &extensionsStr
          );

    string[] dirs = args[1..$];

    if (fileName.empty) {
        stderr.writeln("File name not given");
        return;
    }

    if (dirs.empty) {
        dirs = ["."];
    }

    string[] extensions = extensionsStr.splitter(':').array;

    if (extensions.empty) {
        extensions = [".d"];
    }

    foreach(item; algo(fileName, dirs, extensions)) {
        writefln("Found: %s", item);
    }
}

When I run this it like this (assuming main.d exists):

main --fileName=main

It gives me:

Map: .\main.d
Check: .\main.d
Map: .\main.d
Check: .\main.d
Map: .\main.d
Check: .\main.d
Map: .\main.d
Found: .\main.d

In this simple example it calls map 4 times and filter 3 times. The map transformer and filter predicate can be expensive, so I would want to avoid redundant front evaluations.

The real code is more complicated and can be found here https://github.com/MyLittleRobo/icontheme/blob/master/source/icontheme.d#L427 It can call filter's predicate with the same argument up to 8 times, which is not nice.

Are there ways to fix this? Should I consider writing my own range type probably?

Reply via email to