| Thread overview | ||||||
|---|---|---|---|---|---|---|
|
August 26, 2015 Decrease number of front evaluations | ||||
|---|---|---|---|---|
| ||||
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?
| ||||
August 26, 2015 Re: Decrease number of front evaluations | ||||
|---|---|---|---|---|
| ||||
Posted in reply to FreeSlave | 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? Check http://dlang.org/phobos/std_algorithm_iteration.html#.cache | |||
August 26, 2015 Re: Decrease number of front evaluations | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Yazan D | On Wednesday, 26 August 2015 at 08:30:04 UTC, Yazan D wrote:
> 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?
>
> Check http://dlang.org/phobos/std_algorithm_iteration.html#.cache
I tried it. It can help with map (still calls 2 times though) but the number of filter's predicate calls stay the same.
| |||
August 26, 2015 Re: Decrease number of front evaluations | ||||
|---|---|---|---|---|
| ||||
Posted in reply to FreeSlave | 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
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply