Jump to page: 1 2
Thread overview
Pure delegate not quite pure?
Jun 28, 2015
Tofu Ninja
Jun 28, 2015
Marc Schütz
Jun 28, 2015
anonymous
Jun 30, 2015
Tofu Ninja
Jun 30, 2015
Tofu Ninja
Jun 30, 2015
Tofu Ninja
Jun 30, 2015
Tofu Ninja
Jul 01, 2015
Jesse Phillips
Jul 01, 2015
Tofu Ninja
Jul 01, 2015
Tofu Ninja
June 28, 2015
module main;
import std.stdio;
void main(string[] args)
{
	auto d = foo();
	writeln(d()); // prints 25
}

auto foo()
{
	int x = 4;
	pure int delegate() d = delegate()
	{
		return x*x;
	};
	writeln(d()); // prints 16
	x = 5;
	writeln(d()); // prints 25
	return d;
}

I can see that after foo returns, then d will truly be pure as x will no longer be modifiable, but just before that, it seems d is not actually pure. Is this the intended behavior?
June 28, 2015
On Sunday, 28 June 2015 at 09:19:16 UTC, Tofu Ninja wrote:
> module main;
> import std.stdio;
> void main(string[] args)
> {
> 	auto d = foo();
> 	writeln(d()); // prints 25
> }
>
> auto foo()
> {
> 	int x = 4;
> 	pure int delegate() d = delegate()
> 	{
> 		return x*x;
> 	};
> 	writeln(d()); // prints 16
> 	x = 5;
> 	writeln(d()); // prints 25
> 	return d;
> }
>
> I can see that after foo returns, then d will truly be pure as x will no longer be modifiable, but just before that, it seems d is not actually pure. Is this the intended behavior?

Just guessing: The context is treated as an implicit parameter of `d` (analogous to `this` for a struct/class). Access to `x` counts a access through a parameter and therefore doesn't violate purity.
June 28, 2015
On Sunday, 28 June 2015 at 09:19:16 UTC, Tofu Ninja wrote:
> module main;
> import std.stdio;
> void main(string[] args)
> {
> 	auto d = foo();
> 	writeln(d()); // prints 25
> }
>
> auto foo()
> {
> 	int x = 4;
> 	pure int delegate() d = delegate()
> 	{
> 		return x*x;
> 	};
> 	writeln(d()); // prints 16
> 	x = 5;
> 	writeln(d()); // prints 25
> 	return d;
> }
>
> I can see that after foo returns, then d will truly be pure as x will no longer be modifiable, but just before that, it seems d is not actually pure. Is this the intended behavior?

Here's a similar example where it's a bit clearer what's going on:
----
struct S
{
    int x = 0;
    int d() pure {return ++this.x;}
}
void main()
{
    S s;
    int delegate() pure d = &s.d;
    import std.stdio;
    writeln(d()); /* prints "1" */
    writeln(d()); /* prints "2" */
    writeln(d()); /* prints "3" */
}
----

`d` isn't all that pure, right? You're seeing the concept of "weak purity" in action. In D, the attribute `pure` really just means "doesn't access global mutable state". The function is still allowed to mutate any arguments it gets, including hidden ones. Here the method `d` has a hidden `this` parameter, and it can mutate data through it. With a nested function, the enclosing context is passed via a hidden parameter.

Properly/mathematically/strongly pure functions have additional requirements on top of being marked `pure`. Read more here:
http://klickverbot.at/blog/2012/05/purity-in-d/
June 30, 2015
On Sunday, 28 June 2015 at 10:19:05 UTC, anonymous wrote:
> [...]

Is there any way to annotate the context as const?
June 30, 2015
On 6/30/15 5:23 PM, Tofu Ninja wrote:
> On Sunday, 28 June 2015 at 10:19:05 UTC, anonymous wrote:
>> [...]
>
> Is there any way to annotate the context as const?

const x = 4 ;)

But even if you could annotate just the *reference* as const, it doesn't stop foo from changing it as you did in the example.

-Steve
June 30, 2015
On Tuesday, 30 June 2015 at 21:31:05 UTC, Steven Schveighoffer wrote:
> On 6/30/15 5:23 PM, Tofu Ninja wrote:
>> On Sunday, 28 June 2015 at 10:19:05 UTC, anonymous wrote:
>>> [...]
>>
>> Is there any way to annotate the context as const?
>
> const x = 4 ;)
>
> But even if you could annotate just the *reference* as const, it doesn't stop foo from changing it as you did in the example.
>
> -Steve

Yeah, but I am more worried about d changing x by itself(though foo changing it is still a problem), I have a piece of code that takes a delegate and I want to ensure that it runs in the same way every time once it's given to me.
June 30, 2015
On 6/30/15 5:44 PM, Tofu Ninja wrote:
> On Tuesday, 30 June 2015 at 21:31:05 UTC, Steven Schveighoffer wrote:
>> On 6/30/15 5:23 PM, Tofu Ninja wrote:
>>> On Sunday, 28 June 2015 at 10:19:05 UTC, anonymous wrote:
>>>> [...]
>>>
>>> Is there any way to annotate the context as const?
>>
>> const x = 4 ;)
>>
>> But even if you could annotate just the *reference* as const, it
>> doesn't stop foo from changing it as you did in the example.
>>
>
> Yeah, but I am more worried about d changing x by itself(though foo
> changing it is still a problem), I have a piece of code that takes a
> delegate and I want to ensure that it runs in the same way every time
> once it's given to me.

Have you tried placing const on the function signature? i.e.:

pure int delegate() const d = () const {...

That's how you'd do it (I think, didn't test) if the delegate context pointer was a class/struct.

-Steve
June 30, 2015
On Tuesday, 30 June 2015 at 22:05:43 UTC, Steven Schveighoffer wrote:
> Have you tried placing const on the function signature? i.e.:
>
> pure int delegate() const d = () const {...
>
> That's how you'd do it (I think, didn't test) if the delegate context pointer was a class/struct.
>
> -Steve

Nah, says its only available for non-static member functions.
June 30, 2015
On Tuesday, 30 June 2015 at 22:23:40 UTC, Tofu Ninja wrote:
> On Tuesday, 30 June 2015 at 22:05:43 UTC, Steven Schveighoffer wrote:
>> Have you tried placing const on the function signature? i.e.:
>>
>> pure int delegate() const d = () const {...
>>
>> That's how you'd do it (I think, didn't test) if the delegate context pointer was a class/struct.
>>
>> -Steve
>
> Nah, says its only available for non-static member functions.

Also wouldn't being able to annotate it immutable(also doesn't work) solve both problems. If the context was immutable then everything in it would have to be as well, d couldn't change it and foo wouldn't be able to as well because every thing in the context would have to be immutable. Or maybe I am understanding it wrong.
July 01, 2015
On Tuesday, 30 June 2015 at 22:23:40 UTC, Tofu Ninja wrote:
> On Tuesday, 30 June 2015 at 22:05:43 UTC, Steven Schveighoffer wrote:
>> Have you tried placing const on the function signature? i.e.:
>>
>> pure int delegate() const d = () const {...
>>
>> That's how you'd do it (I think, didn't test) if the delegate context pointer was a class/struct.
>>
>> -Steve
>
> Nah, says its only available for non-static member functions.

hmm, it seems that this would be an appropriate enhancement. It doesn't make sense on a function, but as it relates to delegates I'd say it makes sense to allow const to be added.
« First   ‹ Prev
1 2