digitalmars.D.learn - Decrease number of front evaluations
- FreeSlave (74/74) Aug 26 2015 Example:
- Yazan D (2/5) Aug 26 2015 Check http://dlang.org/phobos/std_algorithm_iteration.html#.cache
- FreeSlave (3/9) Aug 26 2015 I tried it. It can help with map (still calls 2 times though) but
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (26/27) Aug 26 2015 Another option is std.functional.memoize:
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?
Aug 26 2015
On Wed, 26 Aug 2015 08:27:05 +0000, FreeSlave wrote:Are there ways to fix this? Should I consider writing my own range type probably?
Aug 26 2015
On Wednesday, 26 August 2015 at 08:30:04 UTC, Yazan D wrote:On Wed, 26 Aug 2015 08:27:05 +0000, FreeSlave wrote:I tried it. It can help with map (still calls 2 times though) but the number of filter's predicate calls stay the same.Are there ways to fix this? Should I consider writing my own range type probably?Check
Aug 26 2015
On 08/26/2015 01:27 AM, FreeSlave wrote:I would want to avoid redundant front evaluations.Another option is std.functional.memoize: import std.stdio; import std.functional; import std.algorithm; import std.array; void main() { auto r = [ 1, 2, 1 ] .map!(memoize!(delegate(int a) { writefln("map for %s", a); return a; })) .filter!(memoize!(delegate(int a) { writefln("filter for %s", a); return a; })); r.each; } Although there are two 1s, the second one is not evaluated because the result of the first one is used: map for 1 filter for 1 map for 2 filter for 2 Ali
Aug 26 2015