equivariant functions

Benji Smith dlanguage at benjismith.net
Tue Oct 14 19:51:46 PDT 2008


Andrei Alexandrescu wrote:
> Benji Smith wrote:
>> I really don't see what all the fuss is about with the equivariance 
>> stuff, except that it introduces a lot of confusing rules to fix the 
>> holes in the (already complex and confusing) const system.
> 
> Please stop perpetuating misunderstanding and apprehension about the 
> const system through statements strong on opinion and vague on detail. 
> If you're willing to mention holes, complexity, and confusion about the 
> const system, please explain where the holes are, where the complexities 
> lie, and what aspects you are confused about. Suggestions for fixing 
> said issues would also be welcome.

Fair enough. Here are the reasons I describe the const system as "complex":

* Comparable code without const qualifiers contains quantatitively fewer 
semantic constructs than code that uses those qualifiers. Smaller 
function prototypes are easier to read and comprehend:

    char[] join(char[] str2, char[] str2) { ... }

    const(char)[] join(const(char)[] str1, const(char)[] str1) { ... }

* Nestable const type constructors require me to keep a more detailed 
mental model of the type system. Am I using a "const(char)[]" or a 
"const(char[])"?

* Remembering the difference between "const" and "invariant" requires 
more mental energy than using a system (D1) where such distinctions 
don't exist.

* The idea that "const" is a supertype of "mutable" and "invariant" is 
utterly bizarre to me, since it violates the "is a" rule of type 
hierarchies. I understand that, for the sake of overloading, both 
"mutable" and "invariant"  can be implicitly cast to "const", but the 
other implications of that relationship are beyond my grasp at the moment.

* The transitivity of const qualifiers requires me to consider not just 
the object I'm passing around, but the references to other objects 
contained within the const-qualified object.

* Both "const" and "invariant" can apply to value-type objects. But 
"const" doesn't make any sense in that context, so in my mind I have to 
use the "invariant" concept instead whenever applying the concept to a 
primitive value.

* The equivariance proposal, at least in some of its forms, requires me 
to imagine the existence of implicit typedefs at the function-call site, 
and to know that the declared type in my method signature might not be 
the actual type of the arguments received by the function.

The "holes" I described in the const system are the symptoms being 
addressed by the equivariance proposal. Without equivariance, the const 
system sometimes requires verbatim duplication of code within function 
bodies whose only difference is their signature. Without the const 
system, the equivariance proposal wouldn't be necessary.

And the reason I describe the const system as "confusing"?

Because it confuses me.

I understand some of the allure of having a robust, provably correct 
const system. Automatic memoization would be cool. Automatic parallel 
execution would be nice. And, in theory, it'd be nice to avoid errors 
that occur when a piece of code modifies a piece of data that it shouldn't.

But in my experience (using languages that lack any sort of const 
system, except for enum-style declarations), it just doesn't matter 
much. When I need memoization or parallel execution, I write the code 
explicitly. And when I need an immutable object, I design its interface 
to make external mutation impossible (see also: java.lang.String).

It's indisputable that the D2 const system is measurably more complex 
than the D1 const system.

For me, the cost of that complexity significantly outweighs the benefit.

--benji



More information about the Digitalmars-d mailing list