equivariant functions

Steven Schveighoffer schveiguy at yahoo.com
Tue Oct 14 18:13:41 PDT 2008


"Bill Baxter" wrote
> I'm looking at all these funky syntaxes with their many unusual
> implicit assumptions that they require a user to keep in mind, and
> thinking it would all be a lot simpler if you could just declare some
> template-like meta-variables in a preamble to the function.
>
> I also don't like the looks of using a symbol in the return type that
> doesn't get declared till you see the parameter list.
>
> So how about introducing a "typedef block" where you can introduce
> metatypes and give them constraints.
>
> For constness:
>
> typedef {  Const : const }  // in this case means any kind of const
> Const(int) someFunc(Const(int) z) { ... }
>
> For Objects:
>
> class BaseClass {}
> class DerivedClass : BaseClass {}
>
> typedef { DType : BaseClass } // DType is anything passing  is(DType :
> BaseClass)
> DType someFunc(DType input)
>
> For both:
>
> typedef {
>  DType : BaseClass;
>  Const : const
> }
> Const(DType) someFunc(Const(DType) input)
>
> And with something like this you can also come up with some solution
> to the min problem
> typedef{
>   ConstA : const;
>   ConstB : const;
>   ConstC = maxConst!(ConstA,ConstB)
> }
> ConstC(Type) max(ConstA(Type), ConstB(Type))
>
> maxConst would be some template-like thing func to take the "more
> const" of the two qualifiers.  Not sure how you'd implement that.
>
> Lots o hole's there, but the basic idea I'm suggesting is to declare
> the types and qualifiers that can vary in some sort of a preamble
> block.  To me this looks like it will be much more readable and easier
> to maintain than any of these funky syntaxes with lots of implicit
> rules to remember.

I'm not a fan of complexity where it is not required.

You have outlined pretty much exactly the only use cases for this feature. 
So why do you want to continually write large typedefs that are identical in 
front of all your functions, when you can do so with a succinct syntax?

To put the use cases in more english descriptions:

1. I want the constancy of my return to be dependent on the constancy of the 
argument at the call site.
2. I want the constancy of my return to be the greatest common constancy of 
multiple arguments at the call site.
3. The return type will be exactly the same value that I passed in to the 
function, so I can use it for call chaining.  So it's OK to auto cast to the 
most derived type.
4. I want 1 and 3

Where greatest common constancy is defined as const if any arguments differ 
in constancy.  If they don't differ it is defined as the constancy of the 
arguments.

My biggest concern is 1 and 2, since otherwise for 1, we are left with 3 
different versions of the same function, and for 2, we are left with 3^n 
different versions.

3 (and 4) are of mild concern, because you are only forced to redefine once 
per class, and it's not as common a problem, since not all classes require 
handling of call chaining, whereas all classes should be const-aware.

I'll reiterate my proposal:

inout(X) f(inout(Y) y, inout(Z) z)

where inout means 'the greatest common constancy of all variables that are 
declared inout'.  Again, not in love with inout, but inout kind of reads 
'you get out what you put in', and it is a 'free' keyword.

and for 3:

X f(return X x);

where return means 'this function will return x'.  The return statements in 
this function are all required to return the value of x.  (x cannot be 
rebindable inside the function).

-Steve 





More information about the Digitalmars-d mailing list