Thread overview | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
August 20, 2011 How do "pure" member functions work? | ||||
---|---|---|---|---|
| ||||
Does marking a member function as pure mean that it will return the same result given the same parameters, or that it will give the same result, given the same parameters and given the same class/struct members? |
August 20, 2011 Re: How do "pure" member functions work? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Eskapp | On 8/20/11 5:13 PM, Sean Eskapp wrote:
> Does marking a member function as pure mean that it will return the same
> result given the same parameters, or that it will give the same result, given
> the same parameters and given the same class/struct members?
The second one, the implicit this parameter is just considered a normal argument as far as purity is concerned.
David
|
August 20, 2011 Re: How do "pure" member functions work? | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Nadlinger | == Quote from David Nadlinger (see@klickverbot.at)'s article
> On 8/20/11 5:13 PM, Sean Eskapp wrote:
> > Does marking a member function as pure mean that it will return the same result given the same parameters, or that it will give the same result, given the same parameters and given the same class/struct members?
> The second one, the implicit this parameter is just considered a normal
> argument as far as purity is concerned.
> David
Wait, references and pointers are now valid for pure function arguments?
|
August 20, 2011 Re: How do "pure" member functions work? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Eskapp | On 08/20/2011 06:24 PM, Sean Eskapp wrote:
> == Quote from David Nadlinger (see@klickverbot.at)'s article
>> On 8/20/11 5:13 PM, Sean Eskapp wrote:
>>> Does marking a member function as pure mean that it will return the same
>>> result given the same parameters, or that it will give the same result, given
>>> the same parameters and given the same class/struct members?
>> The second one, the implicit this parameter is just considered a normal
>> argument as far as purity is concerned.
>> David
>
> Wait, references and pointers are now valid for pure function arguments?
There are different forms of pure functions:
weakly pure:
no mutable globals are read or written. the function may however change its arguments. weakly pure functions are useful mainly for the implementation of functions with stronger purity guarantees.
const pure/strongly pure:
All function arguments are values or const/immutable.
From the type signature of a function, you can always tell which form of pure function it is:
int foo(ref int, int) pure; // weakly pure, could change first argument
int bar(const(int)*, int) pure; // const pure
int qux(immutable(int)*, int) pure; // strongly pure
Weakly pure member functions can therefore change the other members:
struct S{
int x;
int foo() pure; // weakly pure, could change x
int bar() pure const; // const pure, cannot change x
int qux() pure immutable; // strongly pure, only works with immutable instances
}
The rationale of this:
Consider
int baz(int x) pure{
S s=S(x);
S.foo();
return s;
}
This is clearly strongly pure code. If we had no weakly pure, this could not be written in that way.
|
August 20, 2011 Re: How do "pure" member functions work? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | == Quote from Timon Gehr (timon.gehr@gmx.ch)'s article
> On 08/20/2011 06:24 PM, Sean Eskapp wrote:
> > == Quote from David Nadlinger (see@klickverbot.at)'s article
> >> On 8/20/11 5:13 PM, Sean Eskapp wrote:
> >>> Does marking a member function as pure mean that it will return the same result given the same parameters, or that it will give the same result, given the same parameters and given the same class/struct members?
> >> The second one, the implicit this parameter is just considered a normal
> >> argument as far as purity is concerned.
> >> David
> >
> > Wait, references and pointers are now valid for pure function arguments?
> There are different forms of pure functions:
> weakly pure:
> no mutable globals are read or written. the function may however change
> its arguments. weakly pure functions are useful mainly for the
> implementation of functions with stronger purity guarantees.
> const pure/strongly pure:
> All function arguments are values or const/immutable.
> From the type signature of a function, you can always tell which form
> of pure function it is:
> int foo(ref int, int) pure; // weakly pure, could change first argument
> int bar(const(int)*, int) pure; // const pure
> int qux(immutable(int)*, int) pure; // strongly pure
> Weakly pure member functions can therefore change the other members:
> struct S{
> int x;
> int foo() pure; // weakly pure, could change x
> int bar() pure const; // const pure, cannot change x
> int qux() pure immutable; // strongly pure, only works with
> immutable instances
> }
> The rationale of this:
> Consider
> int baz(int x) pure{
> S s=S(x);
> S.foo();
> return s;
> }
> This is clearly strongly pure code. If we had no weakly pure, this could
> not be written in that way.
Oh, I see, thanks! This isn't documented in the function documentation!
|
August 20, 2011 Re: How do "pure" member functions work? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Eskapp | Sean Eskapp:
> Oh, I see, thanks! This isn't documented in the function documentation!
D purity implementation looks like a simple thing, but it's not simple, it has several parts that in the last months have be added to the language and compiler, and we are not done yet, there are few more things to add (like implicit conversion to immutable of the results of strongly pure functions). It will need several book pages to document all such necessary design details.
Bye,
bearophile
|
August 21, 2011 Re: How do "pure" member functions work? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Eskapp | On Saturday, August 20, 2011 16:53:51 Sean Eskapp wrote:
> == Quote from Timon Gehr (timon.gehr@gmx.ch)'s article
>
> > On 08/20/2011 06:24 PM, Sean Eskapp wrote:
> > > == Quote from David Nadlinger (see@klickverbot.at)'s article
> > >
> > >> On 8/20/11 5:13 PM, Sean Eskapp wrote:
> > >>> Does marking a member function as pure mean that it will return the same result given the same parameters, or that it will give the same result, given the same parameters and given the same class/struct members?> >>
> > >> The second one, the implicit this parameter is just considered a
> > >> normal argument as far as purity is concerned.
> > >> David
> > >
> > > Wait, references and pointers are now valid for pure function arguments?>
> > There are different forms of pure functions:
> > weakly pure:
> > no mutable globals are read or written. the function may however change
> > its arguments. weakly pure functions are useful mainly for the
> > implementation of functions with stronger purity guarantees.
> > const pure/strongly pure:
> > All function arguments are values or const/immutable.
> >
> > From the type signature of a function, you can always tell which form
> >
> > of pure function it is:
> > int foo(ref int, int) pure; // weakly pure, could change first argument
> > int bar(const(int)*, int) pure; // const pure
> > int qux(immutable(int)*, int) pure; // strongly pure
> > Weakly pure member functions can therefore change the other members:
> > struct S{
> >
> > int x;
> > int foo() pure; // weakly pure, could change x
> > int bar() pure const; // const pure, cannot change x
> > int qux() pure immutable; // strongly pure, only works with
> >
> > immutable instances
> > }
> > The rationale of this:
> > Consider
> > int baz(int x) pure{
> >
> > S s=S(x);
> > S.foo();
> > return s;
> >
> > }
> > This is clearly strongly pure code. If we had no weakly pure, this could
> > not be written in that way.
>
> Oh, I see, thanks! This isn't documented in the function documentation!
The documentation takes the approach of saying what functions can be pure but not how they can be optimized. Essentially, any function which doesn't access any mutable global state and doesn't call any functions which aren't pure can be pure. Weak and string purity come in when optimizing. Additional calls to weakly pure functions can't be optimized out, because they can alter their arguments. Additional calls to strongly pure functions _can_ be optimized out, because the compiler can guarantee that its arguments aren't altered.
At present, a strongly pure function is a pure function where all of its parameters (including the invisible this parameter) are either immutable or implicitly convertible to immutable. But that could be expanded to include pure functions whose parameters are all either const or implicitly convertible to const in cases where the compiler knows that the function is being passed immutable variables. So, right now, David is incorrect in thinking that
int bar(const(int)*, int) pure;
is strongly pure, but in the future, it probably will be in cases where it's passed an immutable pointer.
- Jonathan M Davis
|
August 21, 2011 Re: How do "pure" member functions work? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | bearophile wrote:
> Sean Eskapp:
>
>> Oh, I see, thanks! This isn't documented in the function documentation!
>
> D purity implementation looks like a simple thing, but it's not simple, it has several parts that in the last months have be added to the language and compiler, and we are not done yet, there are few more things to add (like implicit conversion to immutable of the results of strongly pure functions). It will need several book pages to document all such necessary design details.
>
> Bye,
> bearophile
It is actually very simple: a function marked as 'pure' is not allowed to explicitly access any static variables.
Everything else is just compiler optimisation, and the programmer shouldn't need to worry about it.
|
August 21, 2011 Re: How do "pure" member functions work? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don | On 08/21/2011 09:10 PM, Don wrote:
> bearophile wrote:
>> Sean Eskapp:
>>
>>> Oh, I see, thanks! This isn't documented in the function documentation!
>>
>> D purity implementation looks like a simple thing, but it's not
>> simple, it has several parts that in the last months have be added to
>> the language and compiler, and we are not done yet, there are few more
>> things to add (like implicit conversion to immutable of the results of
>> strongly pure functions). It will need several book pages to document
>> all such necessary design details.
>>
>> Bye,
>> bearophile
>
> It is actually very simple: a function marked as 'pure' is not allowed
> to explicitly access any static variables.
> Everything else is just compiler optimisation, and the programmer
> shouldn't need to worry about it.
It can be of value to know that a function is pure as in mathematics if it is strongly pure, but can have restricted side-effects if it is weakly pure.
|
August 22, 2011 Re: How do "pure" member functions work? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On Sat, 20 Aug 2011 12:43:29 -0400, Timon Gehr <timon.gehr@gmx.ch> wrote:
> On 08/20/2011 06:24 PM, Sean Eskapp wrote:
>> == Quote from David Nadlinger (see@klickverbot.at)'s article
>>> On 8/20/11 5:13 PM, Sean Eskapp wrote:
>>>> Does marking a member function as pure mean that it will return the same
>>>> result given the same parameters, or that it will give the same result, given
>>>> the same parameters and given the same class/struct members?
>>> The second one, the implicit this parameter is just considered a normal
>>> argument as far as purity is concerned.
>>> David
>>
>> Wait, references and pointers are now valid for pure function arguments?
>
> There are different forms of pure functions:
>
> weakly pure:
> no mutable globals are read or written. the function may however change its arguments. weakly pure functions are useful mainly for the implementation of functions with stronger purity guarantees.
I have to just interject real quick: One aspect of pure functions that usually is forgotten (probably because it's seldom used) is that pure functions are not allowed to accept or return shared data.
In other words:
pure int foo(ref shared(int) i); // compiler error.
I think even without the ref, it's a compiler error, although I don't see what the point of a shared non-reference type is...
Other than that, you got everything right.
-Steve
|
Copyright © 1999-2021 by the D Language Foundation