[Python-ideas] Infix functions

Andrew Barnert abarnert at yahoo.com
Sat Feb 22 23:59:42 CET 2014


From: Hannu Krosing <hannu at krosing.net>

Sent: Saturday, February 22, 2014 11:34 AM


> On 02/22/2014 03:45 AM, Andrew Barnert wrote:
>>  Sure, having an infinite number of easily-distinguishable operators that 

>> happen to have the precedence that fits your use case would be create. But we 
>> have a very limited set of operators. If you want element-wise multiplication, 
>> div, trued, and mod, there aren't any operators left with the right 
>> precedence for cross-multiplication, dot-product, and back-division. And even if 
>> that weren't an issue, using % to mean mod sometimes and cross-product other 
>> times is bound to be confusing to readers.


> Why not use multiple "operator characters" for user-defined infix
> operators, like postgreSQL does ?
> 
> a *% b ++ c *% (d *. e)

First, I'm not sure why everyone is focusing on the mathematical examples. As I said front he start, I think NumPy and friends have mostly solved the problem of doing math readably in Python, and the only reason custom operators would likely be useful would be if we had _other_ use cases, probably (but not necessarily) akin to the higher-order functions people frequently inline in Haskell. Of course in Haskell, many of those _are_ written as symbols, but I doubt anyone wants that for Python. I could see "spam `compose` eggs" in Python, but not "spam . eggs".

Anyway, sticking with the mathematical cases, Haskell does what you're proposing. And it was discussed for Python Numeric in the 2.1 days. I don't think PEP 225 covers why they rejected the idea in favor of just doubling the number of operators by adding a special ~ prefix, but there are two major problems.


First, none of those sequences has any inherent meaning. I can guess what @cross means. If you just double the set of operators by allowing a ~ prefix, I can guess that ~* is a variant on multiplication (I do have to know whether you're using ~* for element-wise and * for object-wise, Matlab-style, or vice-versa, R-style, but that's just one piece of information per project). If you have a whole suite of free-form operators made up of symbol strings, I have absolutely no idea what *% means. Maybe you know what you intended there, but would you know after three weeks of working on a different project? This is a serious problem with Haskell; I can't read someone's code unless I have his project's operator-defining stub open so I know whether he used <. for sorting, compose-composing, backward folding, or something I never even heard of that I have to work through.

Second, many such sequences are ambiguous. What does 3*.2 mean? Is it your custom *. operator, or a normal * multiplying 3 and .2? It's not just the dot; + and - are unary prefix operators, = is a different kind of syntax, etc. You could use whitespace to distinguish, so 2 %+ 3 is op%+(2, 3) but 2%+3 is mod(2, +3), but that's a pretty big change to the way the parser works. Also, there's a reason the "spaces around binary operators" rule is in the PEP 8 style guide rather than the language: usually it makes your code more readable to follow the guideline, but sometimes it makes it less readable.

> We could even define that the characters in the combined operator define

> precendece so the
> above could be written as
> 
> a *% b ++ c *% d *. e
> 
> where *% has higher precedence than *. because of (* is higher than %)
> and *. has higher
> precedence than *% because (. is gher than %)


Well, * and % are actually the same precedence in Python, and . isn't an operator so it doesn't have a precedence, but I get your point.

This has been discussed for Haskell a few times; see the thread starting http://www.haskell.org/pipermail/haskell-cafe/2006-October/018884.html for one example. I don't know that anyone ever thought it through for Python.

It might work. It would certainly encourage people to use operators starting with * only to use multiplication-like things instead of whatever-they-want, since it's going to get multiplication-like precedence and associativity. It might be worth working through some detailed examples.


More information about the Python-ideas mailing list