equivariant functions

Michel Fortin michel.fortin at michelf.com
Mon Oct 13 05:08:47 PDT 2008


On 2008-10-12 15:34:05 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail at erdani.org> said:

> 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.

I'm not sure why one would one add another syntax feature for this. I 
mean: we have templates which are capable of this. Sure, templates are 
instanciated only when needed and that's not what we want, but I think 
we'd better reuse the syntax we have, adding a modifier and if 
necessary for forcing one instanciation at the definition site when 
possible.

I'm not sure if this is valid in D2 (I don't have a D2 compiler in 
front of me right now), but let's say that this makes C any subtype of 
const(char):

	C strip1(C : const(char))(C[] s);

This template does what you want, except that it's instanciated only at 
the call site, making it unusable in some situations. What we need is 
to make this specific template work like C# and Java's generics: only 
one instanciation dealing with multiple parametrized types. So let's 
extend the template syntax a little:

	C strip1(equivariant C : const(char))(C[] s);

Hum, what did that change? Well, the new "equivariant" keyword I added 
imposes new restrictions to the template argument, such as you cannot 
know the exact type beyond the type restriction in the parameter 
definition. These restrictions are designed to enable only one 
instanciation of the template to cover them all. For instance:

	C strip1(equivariant C : const(char))(C[] s)
	{
		C[] s1 = s; // okay, s1 is of the same type.
		C[] s2 = "abc"; // error, "abc" is invariant(char)[],
		                // incompatible with base type const(char)[]
		C[] s2 = new C[5]; // can allocate since we know we deal with "char",
		                   // whatever constness it has, it'll always be of 
the same size.
		return s; // okay, same type.
	}

Reusing the template syntax would avoid adding yet another different 
but similar syntax for generic functions. Perhaps you find the template 
syntax overly verbose for this (I do), but then I'd say it's the 
template syntax that ought to be rethought instead reinventing it in 
another more limited form for equivariant functions.

(Of course we could start from an equivalent function syntax and then 
extend it to templates later, so I'm not really against what you're 
exposing here. I only wish we can reach some syntax consistency in the 
end.)

-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/




More information about the Digitalmars-d mailing list