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