I think that the obvious and extremely compelling operators exist and adding new operators would only benefit specific domains.
I’m pretty much with you (even though I suggested =~ above), I really don’t think there is much use for a lot of esoteric operators. Even something like =~ seems of extremely limited utility.
It might be helpful to list first chars (or sequences of chars) that can’t possibly be used as operators or operator prefixes given the current grammar. Then we could limit discussion to which remaining chars or sequence of chars could reasonably be used for operators without completely breaking the current grammar. From that, we might be able to spot some combinations/sequences that suggest useful operators to reserve.
My preference would be to pretty much stick to operators that have a mathematical meaning (though that is open to interpretation obviously). Another possibility would be to consider a single character or opening/closing characters that can be used to delimit custom operators. For example, all “Custom Operators” would be of the form:
where OP could be any sequence of characters [A-Za-z!@#$%^&*()-_+={}[]|;:’"<>,.?/`] or something like that (not sure if we’d want OP to be permitted to be that arbitrary or not.
So, you could possibly define operators like:
- Floor Function: ~_~ or ~floor~
- Ceiling Function: ~^~ or ~ceil~
- Determinant (Matrix): ~||~ or ~det~
- Dot Product: ~.~ or ~dotp~
- Cross Product: ~x~ or ~xprod~
- Factorial: ~!~ or ~fact~
- Sequence Sum: ~++~ (aka Sum elements of an iterator) or ~sum~
- Sequence Product: ~**~ or ~prod~
You get the idea.
It would be nice to be able to have some syntax for pre-fix vs post-fix vs infix operators. Something like:
- Pre-fix Operator: ~OP>~
- Post-fix Operator: ~<OP~
- In-fix Operator: ~OP~
Of the above, I actually would prefer the spelled out versions so they are kind of “infix” function calls rather that operators perse (although that’s all operators are after all). I would find ~xprod~ much more readable than ~x~ for example, and not really that much more to type. Also, this would allow easy mapping to custom traits (or easier). So ~xprod~ would be the trait, “Op_xprod” with the function “xprod” or something along those lines.
Honestly though, I really don’t see this being useful. I’m having a real hard time seeing how this doesn’t result in unreadable code and would just be a mess. Perhaps someone smarter than me can see how to make something useful out of this idea.
Another issue with custom operators is how to usefully handle precedence. One idea would be to have a set of pre-defined “precedence groups” that correspond to the base/current operator precedence levels. No new levels could be defined. A customer operator/trait could be assigned a precedence of one of the predefined levels (through annotation/attribute). Again, though, I have a hard time imagining how this wouldn’t be a confusing mess.
EDIT: On further thought, since operators are just short-hand notation for in-fix/pre-fix/post-fix function calls, we could generalize as follows (assuming ~OP~ could work with the grammar OK without serious ambiguities)
For any function impl (including trait impl funcs) ‘fn’ we would have
- fn( a, b )
- fn( a )
- ~fn>~a (pre-fix op)
- a~<fn~ (post-fix op)
- fn( a, b, c )
- a ~fn?~ b ~:~ c (ternary in-fix op)
How useful? Questionable.