D 这个纯函数如何修改非私有状态?
TDPL,p。167: 只要函数中的可变状态是完全临时的(即,在堆栈上分配)和私有的(即,不通过引用传递给可能污染它的函数),那么函数就可以被视为纯函数D 这个纯函数如何修改非私有状态?,d,pure-function,D,Pure Function,TDPL,p。167: 只要函数中的可变状态是完全临时的(即,在堆栈上分配)和私有的(即,不通过引用传递给可能污染它的函数),那么函数就可以被视为纯函数 可变状态是暂时的,因为它在堆栈上,对吗?但这不是私人的。那么如何允许foo()修改m1?此引用被视为函数参数的一部分,并且由于函数是弱纯函数,因此可以修改参数。当状态为时,该被视为输入的一部分,该函数仍然满足具有相同输入的相同输出的条件 考虑这个完全合法的例子,它输出2: import std.stdio : writeln; struct
可变状态是暂时的,因为它在堆栈上,对吗?但这不是私人的。那么如何允许
foo()
修改m1
?此引用被视为函数参数的一部分,并且由于函数是弱纯函数,因此可以修改参数。当状态为时,该
被视为输入的一部分,该函数仍然满足具有相同输入的相同输出的条件
考虑这个完全合法的例子,它输出2
:
import std.stdio : writeln;
struct S
{
int foo = 0;
pure void set(size_t i){ foo = i; }
}
void main()
{
S s;
s.set(2);
writeln(s.foo);
}
据我所知,在TDPL发布后,pure的定义得到了扩展。这本书描述了非常纯的函数。在此之后,出现了两个发展:添加了弱纯函数,允许它们改变参数。此外,还为模板函数添加了纯度推断,这样,即使模板函数没有用pure
pure
修饰,只要模板函数是纯的,就可以使用它的实例化,因为TDPL描述的纯
限制性太强,除了简单的数学函数之类的函数外,没有什么用处。您可以查看当前的定义,但基本上可以归结为:
pure
函数无法访问任何模块级或静态变量,这些变量在程序执行过程中可能会发生变化(它们必须是const
值类型或不可变的
才能从pure
函数访问)
pure
函数不能调用任何非pure
函数
纯
功能无法执行I/O
就这样。没有其他限制。但是,如果要优化纯
函数,使其即使在语句中多次使用,也只能被调用一次,则需要额外的限制。即:
- 函数的参数必须是
不可变的
或隐式转换为不可变的
从理论上讲,这可以扩展到要求函数的参数必须是不可变的
或隐式转换为不可变的
(这样,当给定不可变的
参数时,具有常量
参数的函数可以得到优化),但目前情况并非如此
这种pure
函数有时被称为“强”pure
,而那些无法优化的函数则被称为“弱”pure
。TDPL强烈地描述了纯函数。添加了弱pure
函数,以使pure
更通用
虽然弱pure
函数可以改变它们的参数,但它们不能改变全局状态,因此当它们被强pure
函数调用(不能改变它们的参数)时,保证强pure
函数的返回值对于相同的参数始终保持不变。本质上,因为弱pure
函数不能改变全局状态,所以它们是从中调用的强pure
函数的私有状态的一部分。因此,它与Andrei在第5.11.1.1节pure
中描述的非常一致,就像TDPL中的pure
一样,只是函数的私有状态已经扩展,允许函数在不改变全局状态的情况下改变其私有状态
另一个自TDPL以来添加的关于pure
的主要注意事项是函数属性推断<代码>纯
、无行
和@safe
是为模板化函数推断的(但不是为正常函数)。因此,如果模板化函数可以是纯的
,那么现在它是纯的
。它的纯度取决于它用什么实例化。因此,可以将pure
与模板化函数一起使用,而以前,通常不能,因为如果将其设置为pure
,则无法与不纯函数一起使用。但是如果您没有使它成为纯的,那么您就不能将它与纯的函数一起使用,因此这是纯的一个主要问题。幸运的是,属性推理现在解决了这个问题。只要一个模板函数在实例化时遵循上面列出的规则,那么它就被认为是纯的
我想我必须接受这种情况,并习惯于纯空opIndexAssign(T值,size_T I){…}
和纯T opIndex(size_T I)const{…}
只需将pure
看作是函数无法访问可变全局状态的意思,然后让编译器在可以的时候对其进行优化。是的,pure
修饰符最终得到的函数比那些功能上的pure
修饰符更多,但仍然是使功能上的pure
函数成为可能并得以优化的原因。我一直在尝试清理标签,因为它有时指纯虚拟函数,有时是对的,有时是对的。但我对这件事一无所知。你能确认我的标签编辑是否合适吗?将适用于此问题-我创建了,因此如果有效,我认为最好使用现有标记。@RichardJPLeGuen Pure如中所示,因此Pure函数适用于此问题。纯粹是功能性的,没有那么多。。。虽然被列在维基百科页面的相关链接中。
import std.stdio : writeln;
struct S
{
int foo = 0;
pure void set(size_t i){ foo = i; }
}
void main()
{
S s;
s.set(2);
writeln(s.foo);
}