www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 13877] New: Problem with map+join

https://issues.dlang.org/show_bug.cgi?id=13877

          Issue ID: 13877
           Summary: Problem with map+join
           Product: D
           Version: D2
          Hardware: x86
                OS: Windows
            Status: NEW
          Severity: normal
          Priority: P1
         Component: Phobos
          Assignee: nobody puremagic.com
          Reporter: bearophile_hugs eml.cc

This shows a different computational complexity using apparently equivalent
range-based code:


import std.stdio: writeln;
import std.algorithm: map, join;

uint count1, count2;

const(int)[] foo1(in int[] data, in int i, in int max) {
    count1++;

    if (i < max) {
        typeof(return) result;
        foreach (immutable n; data)
            result ~= foo1(data, i + 1, max);
        return result;
    } else {
        return data;
    }
}

const(int)[] foo2(in int[] data, in int i, in int max) {
    count2++;

    if (i < max) {
        return data.map!(n => foo2(data, i + 1, max)).join;
    } else {
        return data;
    }
}

void main() {
    const r1 = foo1([1, 2, 3, 4, 5], 1, 7);
    writeln(count1); // 19531
    const r2 = foo2([1, 2, 3, 4, 5], 1, 7);
    writeln(count2); // 1111111
    assert(r1 == r2); // Results are equally correct.
}


I think such performance traps should not be present using ranges.


The right complexity is restored using:

return data.map!(n => foo2(data, i + 1, max)).cache.joiner.array;

--
Dec 19 2014