On Wed, 23 Feb 2011 15:28:32 -0500, bearophile <bearophileh...@lycos.com>
wrote:
Steven Schveighoffer:
I see zero value in disallowing comparing pointers in D.
I have not suggested to disallow comparing all pointers. I have
suggested to disallow it only for pointers/references allocated inside a
pure function, that are @transparent.
That's not what your example showed. It showed comparing two allocated
pointers *outside* a pure function, and expected them to be equal. I see
that as disallowing all pointer comparisons.
What kinds of problems does pointer comparison cause? I know of none.
If you compare pointers created in a pure function, you are breaking the
most important constraint of pure functions. A pure function is
deterministic. D pure function aren't deterministic, because the value
of the memory pointers they return can be different across different
calls. If you leave this hole in pure functions, then their purity is
much less useful, you can't perform optimizations, you can't reason
about code like you are able to do with pure functions.
Currently you are able to write functions like:
pure bool randomPure() {
int[] a1 = new int[1];
int[] a2 = new int[2];
return a1.ptr > a2.ptr;
}
This is the first real example you have made that shows a problem! It
uses all valid constructs within pure functions (without casts), and by
current rules could be considered strong-pure, however, it violates the
rule of pure that the same parameters should result in the same answer.
Is this function pure? It returns a pseudo-random boolean. You are free
to define this function as pure, but this form of purity is much less
strong than what people think of "pure".
I would not define the function as pure. The questions to answer are:
1. Can the compiler detect valid reference comparisons without annotation?
2. Is this going to be a common problem?
At first glance, I'd say the answer to number 2 is no. Most people are
not going to use the randomness of the memory allocator to subvert
purity. It's unlikely that you accidentally write code like that.
The answer to number 1, I don't know. I don't think the compiler can
determine the origin of allocated memory without annotation.
With the type system change I have prosed it becomes:
pure bool randomPure() {
@transparent int[] a1 = new int[1];
@transparent int[] a2 = new int[2];
return a1.ptr > a2.ptr; // compile-time error, their ptr are
@transparent, so they can't be read
}
I can see now the value in this. I just wonder if it would be worth it.
Seems like such a rare bug to create a whole new type constructor.
It also has some unpleasant effects. For example, the object equality
operator does this:
bool opEquals(Object o1, Object o2)
{
if(o1 is o2)
return true;
...
}
So this optimization would be unavailable inside pure functions, no? Or
require a dangerous cast?
Would it be enough to just require this type of restriction in pure @safe
functions?
I feel that a new type of reference is likely overkill for this issue.
Showing an
assert that two pointers are not equal is not evidence of an error, it's
evidence of incorrect expectations.
One of the main purposes of a type system is indeed to disallow programs
based on incorrect expectations, to help programmers that may not always
remeber what the incorrect expectations are :-)
My point in the above statement is that when you say:
auto a = new int[1];
auto b = new int[1];
assert(a.ptr == b.ptr);
is not evidence of an error :) This is what you did previously.
-Steve