equivariant functions

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Sun Oct 12 12:34:05 PDT 2008


Many functions return one of their parameters regardless of the way it 
was qualified.

char[] stripl(char[] s);
const(char)[] stripl(const(char)[] s);
invariant(char)[] stripl(invariant(char)[] s);

Stripl is not a particularly good example because it needs to work on 
wchar and dchar too, but let's ignore that aspect for now.

There's been several proposals in this group on tackling that problem.

In unrelated proposals and discussions, people mentioned the need for 
functions that return the exact type of this:

class A { A clone(); }
class B : A { B clone(); }

How can we declare A.clone such that all of its derived classes have it 
return their own type?

It took me a while to realize they are really very related. This is easy 
to figure out if you think that invariant(char)[] and char[] are 
subtypes of const(char)[]!

I discussed with Walter a variant that implements equivariant functions 
without actually adding an explicit feature to the language. Consider:

typeof(s) stripl(const(char)[] s);

This signature states that it returns the same type as an argument. I 
propose that that pattern means stripl can accept _any_ subtype of 
const(char)[] and return that exact type. Inside the function, however, 
the type of s is the type declared, thus restricting its use.

I need to convince myself that function bodies of this type can be 
reliably typechecked, but first I wanted to run it by everyone to get a 
feel of it.

Equivariant functions are not (necessarily) templates and can be used as 
virtual functions. Only one body is generated for one equivariant 
function, unless other template mechanisms are in vigor.

Here are some examples:

a) Simple equivariance

typeof(s) stripl(const(char)[] s);

b) Parameterized equivariance

typeof(s) stripl(S)(S s) if (isSomeString!S);

c) Equivariance of field:

typeof(s.ptr) getpointer(const(char)[] s);

d) Equivariance inside a class/struct declaration:

class S
{
     typeof(this) clone();
     typeof(this.field) getfield();
     int field;
}

What do you think? I'm almost afraid to post this.


Andrei



More information about the Digitalmars-d mailing list