DIP80: phobos additions

Timon Gehr via Digitalmars-d digitalmars-d at puremagic.com
Wed Jun 24 18:32:21 PDT 2015


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);
         }
     `;
}




More information about the Digitalmars-d mailing list