Steven Schveighoffer:

> That is allowed, and it's expected that a pure function can return  
> different references with identical calls.

A pointer and a "transparent reference" are two different things. That function 
returns a pointer, and a pointer is a value.
If you call a pure function with the same input you need to receive the same 
value. Otherwise it's not pure. If you mean something else, then you have 
redefined the meaning of "pure" so much that the word "pure" is the wrong one 
to use.


> pure functions are not necessarily @safe functions, you can access  
> pointers.

I know what I am currently able to do with pure functions in D. But here we are 
talking about what's the right/good way to design purity (or maybe we are even 
talking about what's the right way to modify D purity).

I presume you have understood what I have explained about transparent 
references.


> Pure functions are 100% about optimization.

Pure means first of all avoiding side effects. A pure function is not allowed 
to do some things, so both the programmer and the compiler are able to use such 
stronger constrains to perform some extra trasnformations normally not allowed 
on impure functions, and the resulting code is safer from certain kinds of bugs.


> An optimization should *never* be assumed.  That is, given  
> a pure function foo that returns a string, it should not be assumed that:
> 
> auto s = foo();
> auto s2 = foo();
> 
> is always factored into
> 
> auto s = foo();
> auto s2 = s;
> 
> It's an optimization, one which the compiler could or could not decide to  
> use.
> 
> However, it *should* be assumed that:
> 
> assert(s == s2);
> 
> That is, the values are the same.

I have suggested an extension of the type system that disallows statically code 
like:
assert(s.ptr == s2.ptr);

because this may break the transparent nature of references coming out of pure 
functions.


> What are your expectations for pure functions?

Allocating memory in a pure function is so useful that I expect D pure function 
to allow it. On the other hand I expect pure functions to behave 
deterministically, same input means same output. To solve this I have suggested 
di disallow reading the value of references/pointers coming out of pure 
functions.


> There is no such guarantee for weakly-pure functions.  There's not even  
> such a guarantee for strong-pure functions.

I know. This is something I'd like to add (well, I am not sure it's 
implementable, I am not sure it's a good idea, etc, so it's just an idea for 
now. And I don't think D will add it).


> To guarantee this would  
> require some sort of memoization, and require optimizations to be followed.

I think no memoization is needed, I think the only change needed is on the type 
system (so there are no effects on runtime. This type system just disallows 
some programs).

I may call them @transparent pointers/references, they are a supertype of 
normal ones:

class Foo() {}
pure @transparent(Foo) bar() {
  return new Foo();
}
Foo bar2() { // not pure
  return new Foo();
}
void main() {
  @transparent Foo f1 = bar(); // OK
  @transparent Foo f2 = bar2(); // OK
  Foo f3 = bar(); // not allowed, Foo is a subtype of @transparent(Foo)
}


On a @transparent Foo reference you are allowed to overwrite it, modify or use 
anything in the class itself, but you are statically allowed to use "is" 
operator on it, because it breaks its transparency (if you cast it to a pointer 
or not transparent, then you punch a hole in this type part of the type system).

Something similar is acceptable for struct pointers too, and arrays:

struct Spam() {}
@transparent Spam* bar3() {
  return new Spam();
}

struct Spam() {}
@transparent int[] bar4() {
  return new int[10];
}

Bye,
bearophile

Reply via email to