这个纯函数如何能够修改非私有状态? [英] How is this pure function able to modify non-private state?
问题描述
TDPL,第2页. 167:
TDPL, p. 167:
,只要函数中的可变状态完全是暂时的(即分配在堆栈上)和 private (即没有通过引用传递给那些可能会污染它),那么该功能可以被认为是纯函数.
as long as the mutable state in a function is entirely transitory (i.e., allocated on the stack) and private (i.e., not passed along by reference to functions that may taint it), then the function can be considered pure.
import std.stdio : writeln;
struct M{
int[4] _data;
pure ref int opIndex(size_t i){ return _data[i]; }
}
pure M foo(ref M m){
m[0] = 1234;
return m;
}
void main(){
M m1 = M([7, 7, 7, 7]);
writeln(m1);
foo(m1);
writeln(m1);
}
// output:
// M([7, 7, 7, 7])
// M([1234, 7, 7, 7])
可变状态是暂时的,因为它在堆栈上,对吗?但这不是私人的.那么如何允许foo()
修改m1
?
The mutable state is transitory because it's on the stack, correct? But it's not private. So how is foo()
allowed to modify m1
?
推荐答案
pure
进行了一些扩展,因为TDPL描述的pure
过于严格,以至于不仅简单数学函数之类的东西.您可以查看在线文档中的当前定义,但实际上可以归结为:>
pure
has been expanded a bit since the release of TDPL, since pure
as TDPL describes turns out to be far too restrictive to be useful beyond simple math functions and the like. You can look at the online documentation for the current definition, but it essentially comes down to this:
-
pure
函数无法访问在程序执行过程中可能发生突变的任何模块级或静态变量(必须是const
值类型或immutable
才能从pure
中访问功能).
pure
functions cannot access any module-level or static variables which can be mutated during the course of the program (they must beconst
value types orimmutable
to be accessed from apure
function).
pure
函数不能调用不是pure
的任何函数.
pure
functions cannot call any functions which are not pure
.
pure
函数无法执行I/O.
pure
functions cannot perform I/O.
就是这样.没有其他限制.但是,如果要优化pure
函数,以使其仅被调用一次,即使它在一条语句中被多次使用,则还有 额外的限制.即:
That's it. There are no other restrictions. However, there are additional restrictions required if a pure
function is going to be optimized such that it only gets called one time even if it's used multiple times within a statement. Namely:
- 该函数的参数必须为
immutable
或隐式转换为immutable
.
- The function's parameters must be
immutable
or implicitly convertible toimmutable
.
理论上可以扩展为要求该函数的自变量必须为immutable
或隐式转换为immutable
(这样,可以在给定具有const
参数的函数时对其进行优化immutable
参数),但目前并非如此.
In theory that could be expanded to requiring that the function's arguments must be immutable
or implicitly convertible to immutable
(so that a function with const
parameters could be optimized when it's given immutable
arguments), but that's not currently the case.
此类pure
函数有时被称为强" pure
,而那些无法优化的函数将被称为弱" pure
. TDPL强烈描述了pure
功能.为了使pure
更通用,添加了功能较弱的pure
功能.
Such pure
functions are sometimes referred to as "strongly" pure
, whereas those which cannot be optimized would be referred to as "weakly" pure
. TDPL describes strongly pure
functions. Weakly pure
functions were added in order to make pure
more generally usable.
虽然pure
个弱函数 可以更改其参数,但是它们不能更改全局状态,因此当它们被强pure
个强函数(不能更改其参数),以保证对于相同的参数,强力pure
函数的返回值将始终相同.本质上,因为弱pure
函数不能改变全局状态,所以它们是从中调用它们的强pure
函数的私有状态的一部分.因此,这与Andrei在5.11.1.1节中的描述非常吻合 pure
就像TDPL中的pure
做一样,不同之处在于该函数的私有状态已扩展为允许以下功能:可以更改其私有状态而无需更改全局状态.
While weakly pure
functions can alter their arguments, they cannot alter the global state, so when they're called by strongly pure
functions (which can't alter their arguments), the guarantee that the strongly pure
function's return value will always be the same for the same arguments still holds. Essentially, because the weakly pure
functions cannot mutate global state, they're part of the private state of the strongly pure
function that they're called from. So, it's very much in line with what Andrei describes in section 5.11.1.1 pure
is as pure
Does in TDPL, except that the private state of the function has been expanded to allow functions which can alter its private state without altering global state.
自TDPL以来,与pure
有关的另一项主要注意事项是函数属性推断.对于模板函数,可以推断为pure
,nothrow
和@safe
(对于正常函数,则为 not ).因此,如果可以将模板化函数 设为pure
,则现在它的就是 pure
.其纯度取决于实例化的内容.因此,可以将pure
与模板函数一起使用,而以前通常不能使用,因为如果将其设为pure
,则不能与不纯函数一起使用.但是,如果您没有将其设置为pure
,则无法将其与 pure
函数一起使用,因此对于pure
.幸运的是,属性推断现在可以解决此问题.只要模板化的函数在实例化时遵循上面列出的规则,就会被视为pure
.
Another major thing of note which has been added since TDPL with regards to pure
is function attribute inference. pure
, nothrow
, and @safe
are inferred for templated functions (though not for normal functions). So, if a templated function can be pure
, now it is pure
. Its purity depends on what it's instantiated with. So, it becomes possible to use pure
with templated functions, whereas before, you usually couldn't, because if you made it pure
, it wouldn't work with an impure function. But if you didn't make it pure
, then you couldn't use it with a pure
function, so it was a major problem for pure
. Fortunately, attribute inference fixes that now though. As long as a templated function follows the rules listed above when it's instantiated, then it's considered pure
.
这篇关于这个纯函数如何能够修改非私有状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!