[Python-ideas] Infix functions

Andrew Barnert abarnert at yahoo.com
Tue Feb 25 04:46:44 CET 2014


From: Steven D'Aprano <steve at pearwood.info>

Sent: Monday, February 24, 2014 5:47 PM


> On Mon, Feb 24, 2014 at 04:11:19PM -0800, Andrew Barnert wrote:
>> 
>>  Every kind of statement in Python would sometimes be useful as an 
>>  expression. You can always wrap the statement in a function, but it 
>>  looks ugly--even with Nick's concise lambda proposal. For example, 
>>  lets say we wrapped with, try/except, and if/else in functions named 
>>  using, catch, and cond:
>> 
>>      data = using(:?.read(), open(path))
>>      buf = catch(:read_file(path), (FileNotFoundError, :'')
>>      b = cond(a, :1/a, :NaN)
>> 
>>  All of these are possible today, 
> 
> You must have a different understanding of "possible" than I do, 
> because they all give me syntax errors.


I explicitly said "even with Nick's concise lambda proposal". Have you worked out an implementation for that proposal and patched your compiler? If not, yeah, you will get syntax errors.

Without that proposal, they're even worse, hence the "even with…":

     data = using(lambda f: f.read(), open(path))
     buf = catch(lambda: read_file(path), (FileNotFoundError, lambda: '')
     b = cond(a, lambda: 1/a, lambda: NaN)

> If you're trying to 

> sell the idea of one new controversial feature, you really shouldn't 
> demonstrate it with another controversial new syntax.


As I already explained, I don't think the infix functions are worthwhile without some fix for lambdas being too obtrusive—whether Nick's or a different one. So, should I just pretend that problem already had a solution and ignore it?

> Let me try to make your argument for you, I hope fairly. You're hoping 

> that by introducing custom infix binary operators, you can replace 
> syntax for (say)
> 
>     result = 23 if condition else 42
> 
> with 
> 
>     result = 23 `if_operator` condition, 42
> 

> or something similar.
>
> The fact that ternary if already exists isn't 

> important here -- it is your argument that if we had custom infix 
> operators, we wouldn't have needed to add ternary if.
>
> I don't think this suggestion comes even close to working well. Without 

> proper support interpreter support for ternary operators, forcing three 
> arguments around a binary operator is never going to look right, and 
> may have precedence issues. 

You say you're trying to be fair here, but then why have you ignored the two cases that are binary (which I listed first), and then rearranged the third case to make it harder to parse and to read?

Yes, the if expression we ended up with is also out-of-order. But I wrote the function in the order of the if statement, the ternary if expression in most other languages, and the initial proposals that everyone wanted until nobody could get the syntax right. And that makes it a lot clearer: it's a binary operator between a condition and a tuple of then/else values. (Sure, that makes it read more like a two-case indexed switch than an if, but it's still a lot better than the way you wrote it.)

> And it lacks support for lazy evaluation, 


I've mentioned from the start, and repeatedly, that this relies on some other solution to that problem, like Nick's concise lambdas. I don't know how else I can say it at this point that will stop someone from saying, "But that doesn't solve lazy evaluation."

> None of which are as good as the syntax we have for ternary if.

Which, again, I explicitly said multiple times, including in the very section of the message you're replying to.

> This suggests that dedicated syntax beats custom syntax.

Yes. That's almost _universally_ true.

But that doesn't mean you should create dedicated syntax for every kind of expression anyone ever dreams up. That way lies madness, or at least Lisp.

The bar is very high for what deserves dedicated syntax. The except expression may just barely pass it, but the verdict is still out; the with expression doesn't seem likely to clear; some expression that you need for your own project like piping to an Erlang-style channel or binding two dataflow variables definitely won't.

> I'll be honest, it seems to be *so grossly and fundamentally unworkable* 

> to me that I'm kind of astonished that you've raised it not once but 
> twice, instead of discarding it as ridiculous, like the idea of a paper 
> submarine or a hot iron balloon. Perhaps there are other requirements 
> needed to make this work that you haven't mentioned and I haven't 
> thought of? Sorry to be so dismissive, but that's the truth of it.


If you want me to be honest, I think you haven't actually read most of what I've mentioned. Otherwise, you wouldn't be repeating things that I said as if they were arguments I'd never considered, or trying to imagine what something might look like directly under an example of what it looks like.

Here's another example:


> If we've missed one or two use-cases, perhaps we can add operator 
> support for those, e.g. "spam" - "eggs" (whatever that might 
> mean!), 
> without needing to over-generalise the concept to support arbitrary 
> operators everywhere.


Here's what I said in a previous reply to you:

> Turning with and except into readable expressions without needing to add new custom syntax for each was my initial motivation. It's possible there are only a handful of such cases, and only one of them is important enough to be worth doing, in which case custom syntax for that one is the best answer.


So, do you really think that I haven't considered the possibility that, if there are only one or two use-cases. dedicated custom syntax for those one or two use cases are a better answer, because I only said that about "one" rather than "one or two"? Or are you just assuming that you know the arguments and don't need to read them?


More information about the Python-ideas mailing list