I recently found myself wanting an algorithm to apply f(x) repeatedly, generating an infinite sequence, for a variety of reasons. One of those reasons is to generate ancestor directories. Typically when I desire such a thing, I find myself trying to find the existing algorithm which does this already. I eventually realised that recurrence is exactly what I need, if I just simplify it a little for this case.

import std.range;
import std.algorithm;
import std.path;
import std.file;
import std.stdio;

auto unaryRecurrence(alias func, T)(T initialValue) {
return recurrence!((values, index) => func(values[0]))(initialValue);
}

void main() {
    // Print all directories from this one up to and including /.
    getcwd()
    .unaryRecurrence!dirName
    .until("/", OpenRight.no)
    .each!writeln;
}


This is kind of neat. My question is, should something like this function be included in std.range? Either way, it turned into an example of something cool you can do with D.

While I was at it, I noticed that we could also consider a second form of recurrence which permits functions which accept a single argument, with only the Cycle. In that case, the range behind the recurrence could be potentially optimised to only hold the values, and forget about the index. It wouldn't be too far off from how foreach works. Then my function above would have had this lambda instead:

x => func(x[0])

Reply via email to