There is precedence for this in phobos with schwatzSort: It use a
unaryFun, followed by a binaryFun.
I've found this works quite well: More often than not, a unary
fun is more than enough (the default "a < b"/"a == b" is fine).
And in the cases where you *do* need binary comparison, then
having a unary fun anywas is fine. EG:
"MHklfsJKGsfd".byGroup!(std.uni.tolower, "a < b")();
I think it is both an elegant and efficient approach. That's what
I'd go for.
-------
I think we should handle non-commutative predicates. It's not
actually *that* much more complicated. Instead of storing in each
Group a value + range, simply save the range twice, and have one
range be 1 step ahead of the first. I think a few phobos algos do
this. minPos does something kind of similar.
The "overhead" is an initial extra save yes, but the cost of each
pop is to simply pop both ranges (no extra saves there). You
never actually have to make element copies (which may fail if the
range holds const elements to boot...). Also, if the ElementType
is big, then storing an extra range has good chances to actually
take up *less* room.
My stance is that supporting this would be a powerful and useful
tool, and I don't think there'd be that much overhead either, so
I say let's go for it.