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