Bug 14037 – Problem with BigInt and std.functional.memoize
Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P1
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2015-01-24T21:49:00Z
Last change time
2015-02-04T11:22:27Z
Assigned to
nobody
Creator
bearophile_hugs
Comments
Comment #0 by bearophile_hugs — 2015-01-24T21:49:38Z
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.
Comment #1 by sinkuupump — 2015-01-31T16:06:48Z
Error on assigning to AA of BigInt seems a compiler problem: https://issues.dlang.org/show_bug.cgi?id=14089
However, memoize shouldn't assume that an overloaded opAssign returns the object. So I think your fix to memoize is necessary.
Comment #2 by sinkuupump — 2015-02-04T11:22:27Z
The compiler problem was fixed. Closing.
> However, memoize shouldn't assume that an overloaded opAssign returns the object. So I think your fix to memoize is necessary.
Ignore this. I didn't know that AA assignment expression always returns object on rhs.