Thread overview
Question about pure functions
Sep 16, 2013
Bienlein
Sep 16, 2013
anonymous
Sep 16, 2013
Bienlein
Sep 16, 2013
Jonathan M Davis
September 16, 2013
Hello,

ich habe a pure method bar() in a class Foo:

class Foo {
	int i = 0;
	
	void bar() pure {
	    i++;
	}	
}

main() {
	auto foo = new Foo();
	foo.bar()	
}

The pure method bar changes the inst var i. Nevertheless, the
code above compiles and runs which I find confusing. I assumed
that changing an inst var by a pure function is considered
creating a side efect. But the compiler has no problems with this.

Am I getting something wrong here? Thanks for any hints.
Regards, Bienlein
September 16, 2013
On Monday, 16 September 2013 at 07:01:52 UTC, Bienlein wrote:
> Hello,
>
> ich habe a pure method bar() in a class Foo:
>
> class Foo {
> 	int i = 0;
> 	
> 	void bar() pure {
> 	    i++;
> 	}	
> }
>
> main() {
> 	auto foo = new Foo();
> 	foo.bar()	
> }
>
> The pure method bar changes the inst var i. Nevertheless, the
> code above compiles and runs which I find confusing. I assumed
> that changing an inst var by a pure function is considered
> creating a side efect. But the compiler has no problems with this.
>
> Am I getting something wrong here? Thanks for any hints.
> Regards, Bienlein

(Weak) pure functions are allowed to mutate their arguments. Methods take the object via a hidden parameter, so that's an argument, too.

Mark all parameters const to get a strong pure function. For "this" const goes on the method:

class Foo {
	int i = 0;
	
	void bar() const pure {
	    // can't mutate i here
	}
}

See also: http://dlang.org/function.html#pure-functions
September 16, 2013
> Mark all parameters const to get a strong pure function. For "this" const goes on the method:
>
> class Foo {
> 	int i = 0;
> 	
> 	void bar() const pure {
> 	    // can't mutate i here
> 	}
> }
>
> See also: http://dlang.org/function.html#pure-functions

I see, thanks a lot. I like this pure feature and was already
disappointed. Scala doesn't have it (has to remain interoperable
with Java), so I was really happy to see it in D. Your answer
saved my day :-)

-- Bienlein
September 16, 2013
On Monday, September 16, 2013 10:08:22 anonymous wrote:
> Mark all parameters const to get a strong pure function. For "this" const goes on the method:

That's not actually enough. At present, in order for a function to be considered strongly pure, all of its parameters must be either immutable or implicitly convertible to pure (including the this reference). A const reference type is neither.

In principle, a function could be considered strongly pure if its parameters were const but its arguments were immutable, but the compiler isn't that smart about it at this point. The parameters themselves must be immutable or implicitly convertible to immutable.

So, at present, for a member function to be considered strongly pure, it must be an immutable member function, not const. In theory it could be const if the object itself were immutable, but again, the compiler isn't that smart about it at this point. In either case, the actual object would have to be immutable, which is not the case in most code.

And if you make the member functions immutable, they can only be called by immutable objects, forcing you to either duplicate your functions or make it so that your class can only be constructed as immutable.

pure member functions are useful, because they guarantee that the function is not accessing global mutable state, and because it makes it so that they can be called from strongly pure functions, but in general, pure member functions can't be strongly pure and therefore can't be optimized.

If you want to see how many times a pure function is being called, then put a call to writeln inside of a debug {} block inside of it and compile with -debug, since debug blocks are not checked for purity (since they're for debugging). It should then print out every time it's being called, which should allow you to see whether multiple calls with the same arguments within an expression are actually being optimized out (though you might have to compile with -O for the compiler to do the optimizations - I don't know).

- Jonathan M Davis