possible "solution" for ufcs

Timon Gehr timon.gehr at gmx.ch
Mon Jun 6 12:36:06 PDT 2011


Steven Schveighoffer wrote:
> Someone wrote a very compelling argument for ufcs (uniform function call
> syntax) for ranges, and that is, given a slew of range functions, and a
> slew of ranges, it is nice to use a fluent programming syntax to specify
> wrappers for ranges without having to extend each range type.  For example:
>
> take(10,stride(2,cycle([3,2,5,3])));
>
> vs.
>
> [3,2,5,3].cycle().stride(2).take(10);
>
> And I thought damn it would be nice if ranges could implement ufcs, but
> other types that you didn't want to allow infinite extendability could
> avoid it.  That gave me an idea :)
>
>
> import std.stdio;
>
> struct ufcs
> {
>      auto opDispatch(string name, T...)(T args) // appropriate if compiles
> constraint here
>      {
>          mixin("return ." ~ name ~ "(this, args);");
>      }
> }
>
> int foo(ufcs x, int y)
> {
>      writefln("it works! %d", y);
>      return y+1;
> }
>
> void main()
> {
>      ufcs u;
>      auto x = u.foo(1);
>      assert(x == 2);
> }
>
> And it does indeed work (2.053)...
>
> So we can have ufcs without any changes to the compiler, and we also make
> it a *choice* for people who don't want to allow infinite extendability,
> and don't want to deal with possible compiler ambiguities.
>
> The opDispatch could even be a mixin itself (I think).
>
> What do you think?
>
> -Steve

Great! =) This resolves everything around UFCS!

Why has nobody come up with this before? You should definitely file an enhancement
request for phobos.

We just add something like this somewhere:

mixin template implementUFCS() {
    auto opDispatch(string name, T...)(T args) if(is(typeof({mixin("return ." ~
name ~ "(this, args);");}))){
        mixin("return ." ~ name ~ "(this, args);");
    }
}

Each range type will do

    mixin implementUFCS;


And we'll have optional UFCS!!!

A little drawback: Types using implementUFCS will have very bad error reporting if
somebody types a member name wrong:

struct foo{mixin implementUFCS;}
int main(){foo x;x.bar();}

Error: template instance opDispatch!("bar") does not match template declaration
opDispatch(string name,T...) if (is(typeof(delegate ()
{
mixin("return ." ~ name ~ "(this, args);");
}
)))

I think here a change to the compiler would be appropriate at some point so that
we can get:
Error: no property 'bar' for type 'foo'

If opDispatch does not match.

But this is definitely the way to go for UFCS!

Timon




More information about the Digitalmars-d mailing list