Partially pure (Re: Fully transitive const is not necessary)
Michel Fortin
michel.fortin at michelf.com
Fri Apr 4 05:14:12 PDT 2008
On 2008-04-04 01:36:42 -0400, Walter Bright <newshound1 at digitalmars.com> said:
> Don Clugston wrote:
>
>> class C
>> {
>> int numcalls;
>> this() { numcalls=0; }
>> void foo() { ++numcalls; } // Not pure - but no global side effects.
>> }
>>
>> pure int bar(int x)
>> {
>> C c = new C;
>> for (int i=0; i<x; ++i) c.foo();
>> return c.numcalls;
>> }
>>
>> Is bar() pure or not?
>
> I think it is pure, although it might be difficult for the compiler to
> detect it. Like for CTFE, I think the compiler should start out rather
> restrictive about what it regards as pure, and over time expand it as
> it gets more capable.
Personally, I'd rather say foo is pure. I'd define pure as "always
giving the same outputs given the same inputs and having no external
effect". That would make foo pure, because given any object C, it'll
always change C in the same, predictable way.
This definition allows parallelizing loops that wouldn't be
parallelizable if foo wasn't pure (assuming you label foo as pure),
such as this one:
foreach (C c; arrayOfUniqueC)
c.foo();
It also mean that purity doesn't prevent you from altering an out
parameter and that you don't have to make all your parameters
invariant. As long as you only alter what was given to you in the
parameters, since the compiler knows about these parameters from the
call site it can take the decision to parallelize or not, at the call
site. In the example above, if you did this:
C c;
for (int i = 0; i < 10; ++i)
c.foo();
it wouldn't be parallelizable because calling foo alters the state for
the next call. But it's okay, because the compiler can figure that out
from the call site and it won't do the parallelization. In other words,
if the result depends on the previous result, you can't parallelize.
That same situation can happen with a pure function returning a value:
C c;
for (int i = 0; i < 10; ++i)
c = pureFunction(c);
So in other words, altering a non-const parameter isn't a side effect,
it's a predictable effect you can deduce from the function signature,
and I think it should be allowed in a pure function.
P.S.: I'm not sure what would happen if arrayOfUniqueC in the example
above was to contain two or more pointers to the same object. That
would be a problem, and that's why I put the word "unique" in the name
to mean there are no duplicate. I'm not sure how the compiler could
find about that though. Anyway, the worse that can happen is that the
compiler cannot parallelize this particular case without an additional
clue; allowing foo to be pure would still permit the optimization in
the case of the bar function in Don's example, and in any case the
compiler knows there are no duplicate pointers.
--
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/
More information about the Digitalmars-d
mailing list