## digitalmars.D.learn - How do "pure" member functions work?

• Sean Eskapp (3/3) Aug 20 2011 Does marking a member function as pure mean that it will return the same
• David Nadlinger (4/7) Aug 20 2011 The second one, the implicit this parameter is just considered a normal
• Sean Eskapp (2/9) Aug 20 2011 Wait, references and pointers are now valid for pure function arguments?
• Timon Gehr (30/39) Aug 20 2011 There are different forms of pure functions:
• Sean Eskapp (2/42) Aug 20 2011 Oh, I see, thanks! This isn't documented in the function documentation!
• bearophile (4/5) Aug 20 2011 D purity implementation looks like a simple thing, but it's not simple, ...
• Don (5/13) Aug 21 2011 It is actually very simple: a function marked as 'pure' is not allowed
• Timon Gehr (4/22) Aug 21 2011 It can be of value to know that a function is pure as in mathematics if
• Don (12/36) Aug 22 2011 Well, from the compiler's point of view, it's more complicated than
• Simen Kjaeraas (20/23) Aug 22 2011 The concepts are useful, but better names might be worth it. But what
• Don (18/42) Aug 24 2011 @nostatic ?
• Timon Gehr (11/48) Aug 22 2011 What significant optimization do immutable-pure functions benefit from
• Jonathan M Davis (21/73) Aug 22 2011 The _only_ time that subsequent calls to a pure function can be optimize...
• Jonathan M Davis (18/71) Aug 20 2011 The documentation takes the approach of saying what functions can be pur...
• Steven Schveighoffer (10/28) Aug 22 2011 I have to just interject real quick: One aspect of pure functions that ...
Sean Eskapp <eatingstaples gmail.com> writes:
```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?
```
Aug 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
```
Aug 20 2011
Sean Eskapp <eatingstaples gmail.com> writes:
```== 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?
```
Aug 20 2011
Timon Gehr <timon.gehr gmx.ch> writes:
```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.
```
Aug 20 2011
Sean Eskapp <eatingstaples gmail.com> writes:
```== 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!
```
Aug 20 2011
bearophile <bearophileHUGS lycos.com> writes:
```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
```
Aug 20 2011
Don <nospam nospam.com> writes:
```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.
```
Aug 21 2011
Timon Gehr <timon.gehr gmx.ch> writes:
```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.
```
Aug 21 2011
Don <nospam nospam.com> writes:
```Timon Gehr wrote:
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.

Well, from the compiler's point of view, it's more complicated than
that. There are const-pure as well as immutable-pure functions. A
const-pure function has no side-effects, but cannot be optimised as
strongly as an immutable-pure function.

BTW: The whole "weak pure"/"strong pure" naming was just something I
came up with, to convince Walter to relax the purity rules. I'd rather
those names disappeared, they aren't very helpful.

But the basic point is, that knowing that there are no static variables
is hugely significant for reasoning about code. The strong pure/weak
pure distinction is not very interesting (you can distinguish them
using only the function signature).
```
Aug 22 2011
"Simen Kjaeraas" <simen.kjaras gmail.com> writes:
```On Mon, 22 Aug 2011 22:19:50 +0200, Don <nospam nospam.com> wrote:

BTW: The whole "weak pure"/"strong pure" naming was just something I
came up with, to convince Walter to relax the purity rules. I'd rather
those names disappeared, they aren't very helpful.

The concepts are useful, but better names might be worth it. But what
short word eloquently conveys 'accesses no mutable global state'? :p

What we call strongly pure is what in other languages is simply called
'pure', and that is likely the word that should be used for it.

Weakly pure is a somewhat different beast, and the 'best' solution would
likely be for it to be the default (But as we all know, this would
require changing the language too much. Perhaps in D3...). Noglobal
might be the best we have. My favorite thus far is 'conditionally pure'.
It conveys that the function is pure in certain circumstances, and not
in others. However, it might be somewhat diluted by the addition of pure
inference in newer versions of DMD - that definitely is conditionally
pure.

Const pure is not a concept I'm particularly familiar with. Is this the
special case of calling a conditionally pure function with only
const/immutable parameters, with arguments that are immutable in the
calling context, and that it in those cases can be considered
strongly pure?

--
Simen
```
Aug 22 2011
Don <nospam nospam.com> writes:
```Simen Kjaeraas wrote:
On Mon, 22 Aug 2011 22:19:50 +0200, Don <nospam nospam.com> wrote:

BTW: The whole "weak pure"/"strong pure" naming was just something I
came up with, to convince Walter to relax the purity rules. I'd rather
those names disappeared, they aren't very helpful.

The concepts are useful, but better names might be worth it. But what
short word eloquently conveys 'accesses no mutable global state'? :p

nostatic  ?
stateless ?

What we call strongly pure is what in other languages is simply called
'pure', and that is likely the word that should be used for it.

Weakly pure is a somewhat different beast, and the 'best' solution would
likely be for it to be the default (But as we all know, this would
require changing the language too much. Perhaps in D3...). Noglobal
might be the best we have. My favorite thus far is 'conditionally pure'.
It conveys that the function is pure in certain circumstances, and not
in others. However, it might be somewhat diluted by the addition of pure
inference in newer versions of DMD - that definitely is conditionally
pure.

Const pure is not a concept I'm particularly familiar with. Is this the
special case of calling a conditionally pure function with only
const/immutable parameters, with arguments that are immutable in the
calling context, and that it in those cases can be considered
strongly pure?

No, it's where the signature contains const parameters, rather than
immutable ones.
Two calls to a const-pure function, with the same parameters, may give
different results. You'd need to do a deep inspection of the parameters,
to see if they changed.

Consider:

x = foo(y);
x = foo(y);
where foo is const-pure.
Perhaps y contains a pointer to x. In that case, foo could depend on x.
Or, there might be a mutable pointer to y somewhere, and x might have an
opAssign which modifies y.
In each case, the second y is different to the first one.

But, if foo is immutable-pure, it will return the same value both times,
so one of the calls can be optimized away.
```
Aug 24 2011
Timon Gehr <timon.gehr gmx.ch> writes:
```On 08/22/2011 10:19 PM, Don wrote:
Timon Gehr wrote:
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.

Well, from the compiler's point of view, it's more complicated than
that. There are const-pure as well as immutable-pure functions. A
const-pure function has no side-effects, but cannot be optimised as
strongly as an immutable-pure function.

What significant optimization do immutable-pure functions benefit from
that const-pure functions cannot? Is it just that the compiler cannot do
CSE in some cases if there is an impure call in between two const-pure
calls? (which I think would be rather insignificant)

BTW: The whole "weak pure"/"strong pure" naming was just something I
came up with, to convince Walter to relax the purity rules. I'd rather
those names disappeared, they aren't very helpful.

In some contexts they are in fact useful, otherwise the compiler
implementation wouldn't have any use for them.

But the basic point is, that knowing that there are no static variables
is hugely significant for reasoning about code.  The strong pure/weak
pure distinction is not very interesting (you can distinguish them
using only the function signature).

Yes, but saying 'the function is weakly pure' is shorter than saying
'the pure function signature does include mutable references', just like
having a flag set to PUREweak is more efficient than examining the
function signature multiple times.
```
Aug 22 2011
"Jonathan M Davis" <jmdavisProg gmx.com> writes:
```On Monday, August 22, 2011 15:57 Timon Gehr wrote:
On 08/22/2011 10:19 PM, Don wrote:
Timon Gehr wrote:
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.

Well, from the compiler's point of view, it's more complicated than
that. There are const-pure as well as immutable-pure functions. A
const-pure function has no side-effects, but cannot be optimised as
strongly as an immutable-pure function.

What significant optimization do immutable-pure functions benefit from
that const-pure functions cannot? Is it just that the compiler cannot do
CSE in some cases if there is an impure call in between two const-pure
calls? (which I think would be rather insignificant)

The _only_ time that subsequent calls to a pure function can be optimized out
is when all of its arguments are immutable or implicitly convertible to
immutable, otherwise their values could change between calls to the function.
A function whose parameters are all immutable or implicitly convertible to
immutable is always going to be able to be optimized that way, because you
_know_ that it's arguments are immutable or implicitly convertible to
immutable (they _have_ to be). In cases where a pure function whose parameters
are const or implicitly convertible to immutable is passed immutable
arguments, it could be optimized (though that doesn't currently happen), but
if the arguments aren't immutable, then it can't be, because they could change
between calls to the function.

BTW: The whole "weak pure"/"strong pure" naming was just something I
came up with, to convince Walter to relax the purity rules. I'd rather
those names disappeared, they aren't very helpful.

In some contexts they are in fact useful, otherwise the compiler
implementation wouldn't have any use for them.

But the basic point is, that knowing that there are no static variables
is hugely significant for reasoning about code. The strong pure/weak
pure distinction is not very interesting (you can distinguish them
using only the function signature).

Yes, but saying 'the function is weakly pure' is shorter than saying
'the pure function signature does include mutable references', just like
having a flag set to PUREweak is more efficient than examining the
function signature multiple times.

Ultimately, whether pure functions can be optimized or not becomes an
implementation detail. pure functions can't access mutable global state.
That's what pure means. The compiler then does what it can to optimize pure
functions. Weak and strong purity are what determine whether such
optimizations can take place, but I think that Don is basically saying that
that should just be an implementation detail and that what should be focused
on with regards to pure functions is the fact that they can't access mutable
global state.

- Jonathan M Davis
```
Aug 22 2011
Jonathan M Davis <jmdavisProg gmx.com> writes:
```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
```
Aug 20 2011
"Steven Schveighoffer" <schveiguy yahoo.com> writes:
```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
```
Aug 22 2011