On 06/24/2015 11:41 PM, Tofu Ninja wrote:
On Wednesday, 24 June 2015 at 19:04:38 UTC, Wyatt wrote:
On Wednesday, 17 June 2015 at 09:28:00 UTC, Tofu Ninja wrote:

I actually thought about it more, and D does have a bunch of binary
operators that no ones uses. You can make all sorts of weird
operators like +*, *~, +++, ---, *--, /++, ~~, ~-, -~,
>>>--, &++, ^^+, in++, |-, %~, ect...

void main(string[] args){
    test a;
    test b;
    a +* b;
}
struct test{
    private struct testAlpha{
        test payload;
    }
    testAlpha opUnary(string s : "*")(){
        return testAlpha(this);
    }
    void opBinary(string op : "+")(test rhs){
        writeln("+");
    }
    void opBinary(string op : "+")(testAlpha rhs){
        writeln("+*");
    }
}

Oh right, meant to respond to this.  I'll admit it took me a few to
really get why that works-- it's fairly clever and moderately
terrifying.  (I showed it to a friend and he opined it may violate the
grammar.)

But playing with it a bit...well, it's very cumbersome having to do
these overload gymnastics.  It eats away at your opUnary space because
of the need for private proxy types, and each one needs an opBinary
defined to support  it explicitly.  It also means you can't make
overloads for mismatched types or builtin types (at least, I couldn't
figure out how in the few minutes I spent poking it over lunch).

-Wyatt

I am thinking of writing a mixin that will set up the proxy for you so
that you can just write.

struct test
{
      mixin binOpProxy("*");
      void opBinary(string op : "+*", T)(T rhs){
           writeln("+*");
      }
}

The hard part will be to get it to work with arbitrarily long unary
proxies. Eg:
mixin binOpProxy("~-~");
void opBinary(string op : "+~-~", T)(T rhs){
      writeln("+~-~");
}

Obviously you will run into issues with precedence soon, but this should do it:

import std.stdio;
struct Test{
    mixin(binOpProxy("+~+-~*--+++----*"));
    void opBinary(string op : "+~+-~*--+++----*", T)(T rhs){
        writeln("+~+-~*--+++----*");
    }
}

void main(){
    Test a,b;
    a +~+-~*--+++----* b;
}

import std.string, std.algorithm, std.range;
int operatorSuffixLength(string s){
        int count(dchar c){ return 2-s.retro.countUntil!(d=>c!=d)%2; }
        if(s.endsWith("++")) return count('+');
        if(s.endsWith("--")) return count('-');
        return 1;
}
struct TheProxy(T,string s){
    T unwrap;
    this(T unwrap){ this.unwrap=unwrap; }
    static if(s.length){
        alias NextType=TheProxy!(T,s[0..$-operatorSuffixLength(s)]);
        alias FullType=NextType.FullType;
                mixin(`
        auto opUnary(string op : "`~s[$-operatorSuffixLength(s)..$]~`")(){
            return NextType(unwrap);
        }`);
    }else{
        alias FullType=typeof(this);
    }
}

string binOpProxy(string s)in{
        assert(s.length>=1+operatorSuffixLength(s));
        assert(!s.startsWith("++"));
        assert(!s.startsWith("--"));
        foreach(dchar c;s)
                assert("+-*~".canFind(c));
}body{
        int len=operatorSuffixLength(s);
    return `
        auto opUnary(string op:"`~s[$-len..$]~`")(){
            return TheProxy!(typeof(this),"`~s[1..$-len]~`")(this);
        }
auto opBinary(string op:"`~s[0]~`")(TheProxy!(typeof(this),"`~s[1..$-1]~`").FullType t){
            return opBinary!"`~s~`"(t.unwrap);
        }
    `;
}


Reply via email to