Jump to page: 1 2
Thread overview
How do "pure" member functions work?
Aug 20, 2011
Sean Eskapp
Aug 20, 2011
David Nadlinger
Aug 20, 2011
Sean Eskapp
Aug 20, 2011
Timon Gehr
Aug 20, 2011
Sean Eskapp
Aug 20, 2011
bearophile
Aug 21, 2011
Don
Aug 21, 2011
Timon Gehr
Aug 22, 2011
Don
Aug 22, 2011
Simen Kjaeraas
Aug 24, 2011
Don
Aug 22, 2011
Timon Gehr
Aug 22, 2011
Jonathan M Davis
Aug 21, 2011
Jonathan M Davis
August 20, 2011
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
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
== 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
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
== 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
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
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
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
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
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
« First   ‹ Prev
1 2