Okay, this one is going to get fur flying!
It seems clear that for primary types (int32, char, and friends), the
definition of (equals x y) should be obvious.
It seems equally clear that if S is a composite type, all of whose
members consist of primary types, then two elements of type S are equal
exactly if they are memberwise equal.
The introduction of mutability does not alter the above rules.
However...
Note that "tuple" is a reference type. What should
(equal? (tuple #\c) (tuple #\c))
return? If we say that reference type equality is based on identity,
then the answer is #f. If we say that equality is defined by recursive
memberwise equality, then the answer is #t.
My feeling is that the language specification cannot decide this. There
are compelling pragmatic examples where either interpretation of
equality might be demanded. Given which, I am proposing that our
primitive operations should be
equal? (recursive) structural equality
eq? identity equality, which is defined as value
equality for primary types and identity for reference
types
Note that equal? does not admit equality on lambda forms, but eq?
*could* admit identity testing on closures. This would violate the
expectation that
(implies (eq? x y) (equal? x y))
and I am therefore inclined to disallow it. Unfortunately, there is a
problem if it is disallowed.
Consider implementation of a set of objects or a generic collection. In
order to implement fast membership checks and a fast union operation,
every object must have not just an equality check, but a magnitude
check. If we want fast, generic collection implementations, we somehow
need to address this, and it would be really nice NOT to pass a function
pointer to a type-specific magnitude comparator function.
This raises the following somewhat ugly question: do we need to support
magnitude comparison on reference types? What about closures?
I am voting a strong "no" at the present time. If we *do* end up
deciding we require this, then I am going to propose that we introduce
the primitive
(reference->value x)
with the meaning that reference->value applied respectively to K
references will return an identical value for any two references that
are eq?, and will unique return distinct values otherwise (in practice:
the bit pattern corresponding to the pointer). These value distinctions
shall not be required to extend past the next operation that performs
heap-based storage allocation.
If we introduce this, we will certainly need to introduce a new control
form
(without-heap-allocation e)
with the meaning that it is a static error if the expression e
references (recursively) any operation that allocates heap-based
storage. Arguably, the reference->value procedure should ONLY be legal
within this context, but this won't stop some creative nitwit out there
from leaking the integer values, so it probably isn't worth it.
shap
_______________________________________________
bitc-dev mailing list
[email protected]
http://www.coyotos.org/mailman/listinfo/bitc-dev