在D?
中记忆功能时,是否有任何保存纯度的聪明方法?我希望在缓存保存在RAM中的大型数据集的SHA1计算时使用。
答案 0 :(得分:6)
简答:选择记忆或纯度。不要试着兼得。
答案很长:我不知道如何用memoization保存纯度,除非你使用强制转换来欺骗编译器并声称函数是pure
不是,因为为了记忆,你必须存储参数和结果,这打破了纯度,因为pure
函数的首要保证是它们不访问可变的全局或静态变量(是你能记住任何东西的唯一方法。
所以,如果你做了像
这样的事情alias pure nothrow Foo function() FuncType;
auto result = (cast(FuncType)&theFunc)();
然后您可以将theFunc
视为pure
,如果不是pure
,那么由您来确保该函数从外部起作用pure
- 包括交易事实上编译器认为它可以改变返回可变类型的强char[] makeString(size_t len) pure
{
return new char[](len);
}
void main()
{
char[] a = makeString(5);
const(char)[] b = makeString(5);
const(char[]) c = makeString(5);
immutable(char)[] d = makeString(5);
immutable(char[]) e = makeString(5);
}
函数的返回类型的可变性。例如,这段代码将编译得很好
makeString
即使返回类型总是可变的。这是因为编译器知道pure
强烈const
并返回一个无法传递给它的值 - 因此,每次都保证它是一个新值 - 因此改变可变性返回类型为immutable
或makeString
并未违反类型系统。
如果您要在pure
内部执行某项操作,但是当makeString
违反makeString
始终返回新值的保证时,该功能会向pure
投放功能,那么您就会破坏类型系统,根据您对pure
返回的值所做的操作,您可能会冒很多错误的代码。
我知道在没有它时获得纯度的唯一方法是转换函数指针使其为immutable
,但如果你这样做,那么你必须完全理解保证pure
函数的作用以及编译器认为它可以用它做什么,以便您完全模仿该行为。如果您返回{{1}}数据或值类型,这会更容易,因为那时您没有编译器更改返回类型的可变性的问题,但它仍然是非常棘手的业务。
所以,如果您正考虑将某些内容投射到{{1}},请再想一想。是的,有可能做一些你不可能做到的事情,但这是非常危险的。就个人而言,我建议您决定纯度对您来说更重要,或者对您的记忆更重要,而另一方则更重要。其他任何东西都是高风险的。
答案 1 :(得分:0)
D允许在类型系统中表达的是一个不纯的函数,它会记住一个纯函数。
从概念上讲,memoizer也是纯粹的,但类型系统的表达力不足以允许。你需要在某个地方作弊。