Fully transitive const is not necessary
Georg Wrede
georg at nospam.org
Thu Apr 3 17:28:56 PDT 2008
Walter Bright wrote:
> Bill Baxter wrote:
>
>> So does that mean
>>
>> pure int f(const Class c)
>> { ...
>> }
>>
>> will *not* be allowed? Because some part of c *could* change, even if
>> it's not f() doing the changing. I.e. another thread could be
>> changing c concurrently.
>
> Right. That declaration of f is erroneous.
I'd disagree.
Whether a function is pure or not, has nothing to do with whether c
could change or not.
Take, for example sin(x). We all know that it's pure, period. Now,
whether x changes between two consecutive invocations or not, is
irrelevant. Of course you get a different result. And you should.
But pure, IMHO, means (1) the function is guaranteed to give the same
result every time /if/ the input is the same (like sin(x) does), (2) it
does not change anything at all anywhere, it's only way of affecting
life is by its return value, (3) it doesn't access info from
non-constants anywhere.
Now, to the issue between
(1)pure int f(const Class c)
(2)pure int f(Class c)
I'd say that, since a Pure function promises not to change /anything/
(other than its return value, of course) anywhere, this means a pure
function /simply has to implicitly treat its arguments as unchangeable/!
Therefore, depending on what A/W want, either:
- a pure function has to have const decorated parameters only (1)
- and (2) would be a syntax error
or
- a pure function's parameters are implicitly const, and (1) is then a
syntax error
(Not making the latter a syntax error isn't technically impossible, but
for those learning the language and the casual readers of ex. magazine
articles, this would wreak havoc with their understanding D.)
*Back to concurrency*, if someone changes c in mid-run, then it's the
programmer's fault. It's his headache. The function f only guarantees
not to change c /by itself/.
If the programmer wants to guarantee that c doesn't change during f's
invocation, then the invocation of f should be put in a synchronized
block. This might be the case if c has a complicated state (with several
fields).
> A function is pure or it isn't, there really isn't any room for
> "unstable" purity, or the point of purity is lost.
>
> Look at it another way. You can take the value of the bits pushed on the
> stack as arguments to a pure function, and compare that with previous
> bits passed to the same function, and if there's a binary bit match, you
> can skip calling the function and return a previously cached result.
>
> If that cannot be done, then the function is NOT pure.
I wonder if that's so simple when we allow non-POD type arguments?
Of course, if you're speaking metaphorically here, then that's another
thing. But the same literal bit pattern of course could mean the same
object referred to, only that now it suddenly contains other data.
To further clarify,
If a pure function gets a tree t passed to it, and makes a (potentially
very complicated and) deep search into it, then the only thing the
function's pureness guarantees is that if the particular nodes and
leaves it's looked at stay the same, then it should return the same
result the next time.
The rest of the tree could undergo severe changes in between, or even
during an invocation of the pure function, for all it knows. (Of course
this is academic, but tries to illustrate the issue literally.)
In practice we wouldn't want that, but that's not relevant to the
Pureness Issue.
More information about the Digitalmars-d
mailing list