On Wed, 23 Feb 2011 13:13:35 -0500, bearophile <bearophileh...@lycos.com>
wrote:
Steven Schveighoffer:
cast voids all warranties ;)
OK. But that idea is unchanged if you remove the cast and return an int*
from that function.
That is allowed, and it's expected that a pure function can return
different references with identical calls.
Even if the return value is an immutable reference, it is allowed to
return different references with identical calls. You should never expect
that a pure optimization occurs. All you should expect is that a pure
function returns the same value for identical calls. Same value does not
mean the same bits.
Allowing malloc is somewhat exceptional because you then must allow
free.
But I see no reason (yet) to disallow free. If free cannot be pure,
then
malloc cannot be pure.
I suggest to disallow both malloc/calloc and free inside pure functions,
because what malloc returns a pointer, that is a value, that is not
deterministic, it changes across different calls to malloc.
pure functions are not necessarily @safe functions, you can access
pointers.
A weakly pure function
allows one to modularize pure functions, whereas prior to this, things
like sort could not be pure functions, and therefore could not be used
inside pure functions. I think the hole allows pure functions to be
actually usable and easy whereas before they were much too obscure to be
useful in much code.
I think this is unrelated to the hole I was talking about.
Then I don't know of the hole you mean. Pure functions are 100% about
optimization. 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.
If you are going to use casts, then those rules are out the window.
All that is required is to disallow casting.
Disallowing casting is not enough here.
What are your expectations for pure functions?
I have written two more posts after that, but you may have missed them
because I have broken the tread:
http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=130426
Some examples:
class Foo {
int x;
bool opEquals(Foo o) { return x == o.x; }
}
pure Foo bar() {
return new Foo; // OK
}
void main() {
Foo f1 = bar(); // OK
Foo f2 = new Foo;
f1.x = 10; // OK
assert(f1 != f2); // OK
f1 = f2; // OK
assert(f1 is f2); // no
}
Here bar() allocated memory and it's pure, this is OK. f1 is mutable.
You are allowed to call opEquals. You are allowed to overwrite the
reference f1. But you aren't allowed to read the reference f1, because
this breaks the referential transparency of the results of pure
functions.
There is no such guarantee for weakly-pure functions. There's not even
such a guarantee for strong-pure functions. To guarantee this would
require some sort of memoization, and require optimizations to be followed.
The idea is a subtype of pointers/references, that at compile-time
doesn't allow to read the value of the pointer/reference itself. I think
this is able to patch the hole I was talking about (a cast is able to
punch a hole again in this, of course).
I don't see any value in disallowing such accesses. The expectation that
two pure function calls will necessarily return the *exact* same bits when
the function is returning references/pointers is incorrect.
-Steve