6

在 D 中记忆函数时,是否有任何巧妙的方法来保持纯度?

当缓存保存在 RAM 中的大型数据集的 SHA1 计算时,我想要这个。

4

2 回答 2

6

简短的回答:选择记忆或纯度。不要尝试两者兼得。

长答案:我不明白如何通过记忆保持纯度,除非你使用强制转换来欺骗编译器并声称一个函数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的并返回一个无法传递给它的值 - 因此,它每次都保证是一个新值 - 因此将返回类型的可变性更改为constorimmutable不违反类型系统。

如果您要在其中做一些事情makeString,涉及将函数强制转换为何pure时违反makeString始终返回新值的保证,那么您将破坏类型系统,并且您将面临代码非常错误的风险,具体取决于您的内容使用从返回的值进行makeString

pure当你没有它时,我知道获得纯度的唯一方法是强制转换一个函数指针,这样pure就是它可以做到这一点,以便您完全模仿这种行为。如果您要返回immutable数据或值类型,那会更容易,因为这样您就不会遇到编译器更改返回类型的可变性的问题,但这仍然是一件非常棘手的事情。

因此,如果您正在考虑将某些内容投射到pure,请再想一想。是的,有可能以其他方式做不到的事情来做一些事情,但这是非常冒险的。就个人而言,我建议你决定是纯度对你更重要还是记忆对你更重要,然后你放弃另一个。其他任何事情都是高风险的。

于 2013-11-10T22:14:03.867 回答
0

D 允许在类型系统中表达的是一个不纯函数,它记住了一个纯函数。

从概念上讲,memoizer 也是纯粹的,但类型系统的表达能力不足以允许这样做。你需要在某个地方作弊。

于 2013-11-12T16:13:55.747 回答