User-defined Operators

I'm not convinced they should be added but if they are to be added they can be done fairly simply.
x = (foo oper bar)
Equivalent to:
x = oper(foo, bar)
There's a lot of notes to be made though.
  1. oper is looked up in the local (and global) namespaces, not as a method of foo or bar. If you want it to be a method you need to make the local/global function do all the lookups itself.
  2. oper can only be a single name. It cannot be an expression. The reason is that ((foo)(bar)(baz)) is currently legal, meaning (foo(bar))(baz). A limited subset of expressions could be permitted, but I feel it is better to educate users on a "no tolerance" policy.
  3. Custom operators only become really useful when Unicode variable names are permitted.
  4. There's never a question of precedence with this syntax (unlike builtin operators).
  5. Most builtin operators could be altered to use this syntax, but it would make them a bit more verbose. 1+2*3 becomes (1 + (2 * 3)). However, this bloat can be countered by making parsing aware of word boundaries and by making the parenthesis optional under most conditions. Then you return to 1+(2*3).
  6. [Edit] Perhaps the biggest drawback is requiring the user to explicitly import all operators that may be used, ie from math import ×, ≺, ≻, ≼, ≽, ⊀, ⊁, ∈, ∉, ∋, ∌, ⊂, ⊃, ⊄, ⊅, ⊆, ⊇, ⊈, ⊉, ⊊, ⊋, ∩, ∪, ∖, etc. An alternative would be defining a protocol that does use a method of one of the arguments. Unfortunately that significantly increases the complexity of my proposal, so I'll leave it as an exercise for the reader.
I think that's about it. As I said, I'm not convinced they should be added, but if they are I think this is how it should be done.


jto said...

This seems too different from how you overload + and -. I think they should just do this:

x·y == x.__middle_dot__(y)

All the Unicode math symbols have official names. And who wouldn't get a kick out of seeing "def __gt__(self, other)" followed by "def __much_greater_than__" and finally "def __very_much_greater_than__"?

If Unicode identifiers are added to Python--and I think they will be, eventually--presumably they still won't allow math symbols. There is a standard.

Anyway, the most important precondition is an easy way to type those symbols.

Adam Olsen said...

First a side issue, when did you post this comment? Probably a while ago and I somehow missed it. Unfortunately blogger doesn't think it's important to provide a date (let alone in a ISO 8601 format!)

Yes, my idea would be pretty different. This is necessary to provide arbitrary operator names. Your approach would not provide custom operators at all; instead it would turn various math operators into standard builtin operators and allow them to be overriden.

That said, I think yours is a more reasonable approach. Far simpler all around.