Thread overview
operator overload for sh-like scripting ?
Feb 17, 2020
Basile B.
Feb 17, 2020
Adam D. Ruppe
Feb 17, 2020
Simen Kjærås
February 17, 2020
eg

   Sh(echo) < "meh";

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

Not allowed in D - it only does a comparison overload which covers < and > (and <= and >=).

Though we could do strings and stuff. especially with my string interpolation dip https://gist.github.com/adamdruppe/a58f097d974b364ae1cbc8c050dd9a3f we could make it work quite well!
February 17, 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