www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 14037] New: Problem with BigInt and std.functional.memoize

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

          Issue ID: 14037
           Summary: Problem with BigInt and std.functional.memoize
           Product: D
           Version: D2
          Hardware: x86
                OS: Windows
            Status: NEW
          Severity: regression
          Priority: P1
         Component: Phobos
          Assignee: nobody puremagic.com
          Reporter: bearophile_hugs eml.cc

This seems a regression. Now std.functional.memoize has problems with functions
that return a BigInt:


import std.bigint: BigInt;
import std.functional: memoize;

uint fibonacci1(uint n) {
    alias mFib = memoize!fibonacci1; // OK
    if (n < 2)
        return 1;
    else
        return mFib(n - 1) + mFib(n - 2);
}

BigInt fibonacci2(uint n) {
    alias mFib = memoize!fibonacci2; // Error
    if (n < 2)
        return BigInt(1);
    else
        return mFib(n - 1) + mFib(n - 2);
}

void main() {}



dmd 2.067alpha gives:

...\dmd2\src\phobos\std\functional.d(991,9): Error: return expression expected
test.d(13,18): Error: template instance std.functional.memoize!(fibonacci2)
error instantiating


I have seen that the problem can be fixed changing memoize, from this:


template memoize(alias fun)
{
    // alias Args = ParameterTypeTuple!fun; // Bugzilla 13580

    ReturnType!fun memoize(ParameterTypeTuple!fun args)
    {
        alias Args = ParameterTypeTuple!fun;
        import std.typecons : Tuple;

        static ReturnType!fun[Tuple!Args] memo;
        auto t = Tuple!Args(args);
        if (auto p = t in memo)
            return *p;
        return memo[t] = fun(args);
    }
}


To this:


template memoize(alias fun)
{
    // alias Args = ParameterTypeTuple!fun; // Bugzilla 13580

    ReturnType!fun memoize(ParameterTypeTuple!fun args)
    {
        alias Args = ParameterTypeTuple!fun;
        import std.typecons : Tuple;

        static ReturnType!fun[Tuple!Args] memo;
        auto t = Tuple!Args(args);
        if (auto p = t in memo)
            return *p;
        auto result = fun(args);
        memo[t] = result;
        return result;
    }
}



But it looks like a problem of BigInt:

void main() {
    import std.bigint: BigInt;
    int[int] aa1;
    int r1 = aa2[1] = 1; // OK
    BigInt[int] aa2;
    BigInt r2 = aa2[1] = BigInt(1); // Error
}


Gives:


test.d(4,14): Error: undefined identifier aa2, did you mean variable aa1?
test.d(6,24): Error: expression BigInt __aaval1426 = __aaval1426 = BigInt ,
__aaval1426.this(1);

 , 1 in aa2 ? aa2[1].opAssign(__aaval1426) : cast(void)(aa2[1] = __aaval1426)
is void and has no value


So perhaps fixing BigInt suffices.

--
Jan 24 2015