operator overload for sh-like scripting ?

Simen Kjærås simen.kjaras at gmail.com
Mon Feb 17 13:52:11 UTC 2020


On Monday, 17 February 2020 at 13:03:38 UTC, Basile B. wrote:
> eg
>
>    Sh(echo) < "meh";
>
> struct Sh
> {
>      // you see the idea we have op overload for < here
> }

You can't overload < separately - all the comparison operators 
(<, <=, >, >=) are handled via opCmp. Even if you choose to go 
down that route, there are other issues - opCmp needs to return 
something that may be compared to 0, since (a < b) is rewritten 
as (a.opCmp(b) < 0), and the compiler checks if you are simply 
discarding the return value of a comparison, so all in all, you 
shouldn't do that in D (and the hoops you have to jump through to 
make it work makes the code a lot less readable):

struct Sh {
     int opCmp(string s) {
         import std.stdio : writeln;
         writeln(s);
         return 0;
     }
}

unittest {
     Sh sh;
     auto _ = sh < "baz";
}

This is also not chainable, so something like (sh < "foo" < 
"bar") won't work, even with parentheses.

There's also the issue of (a < b) having a defined meaning in D 
(a less than b), and such overloading leads to code that may be 
less readable. This is a point with differing opinions, and I'm 
not firmly on either side of that argument, but it's worth 
pointing out.

Now, if you absolutely want something that's somewhat similar in 
regular D code, there's <<:

struct Sh {
     Sh opBinary(string op : "<<")(string s) {
         import std.stdio : writeln;
         writeln(s);
         return this;
     }
}

unittest {
     Sh sh;
     sh << "foo" << "bar";
}

While this works, it's a design choice that C++ has gotten a lot 
of flak for, including one of my favorite C++ quotes: "I saw 
'cout' being shifted 'Hello world' times to the left and stopped 
right there." There are cases where it's not at obvious to the 
reader of the code what's happening, so such operator overloading 
should be used with caution.

A better choice, perhaps, if using < is important, would be to 
use a DSL and have it obvious in the code that normal D rules 
aren't at play:

void fun() {
     Sh sh;
     mixin dsl!`
         sh < "foo";
     `;
}

At this point though, you're looking at a considerable chunk of 
code just for a bit of syntactic sugar.

--
   Simen


More information about the Digitalmars-d-learn mailing list