[Python-ideas] Syntax for passing lambdas to functions

Andrew Barnert abarnert at yahoo.com
Thu Feb 27 07:16:13 CET 2014


From: Steven D'Aprano <steve at pearwood.info>
Sent: Wednesday, February 26, 2014 8:19 PM


>On Wed, Feb 26, 2014 at 11:44:51AM -0800, Andrew Barnert wrote:
>
>> But it becomes more useful if you do anything else:
>> 
>>     Button("Do it!", on_click() = fire_the_ducks(42))
>> 
>> 
>> At first glance, I think this is nice, 
>
>At first glance, it looks like you are setting the on_click argument to 
>the result of fire_the_ducks(42). 

It's also worth noting that this is exactly the kind of case where Nick's proposal also looks nice:

    Button("Do it!", on_click=:fire_the_ducks(42))


The test is in cases where Nick's syntax looks weird, either because it takes an argument, or because it's more symbols than letters:

    Button("Do it!", on_click=lambda btn: btn.fire_the_ducks(42))

    Button("Do it!", on_click(btn)=btn.fire_the_ducks(42))

    Button("Do it!", on_click=:?.fire_the_ducks(42))


You can try adding whitespace to the Nick version of last example anywhere you want, and it's still going to hurt to look at. But the Greg version looks actually clearer here than in the no-argument case.

>It's really a bad idea to have syntax for a "shorter lambda" 

>that works here:
>
>    f(arg=***whatever***)
>
>but not in these:

I don't think that's _necessarily_ a problem. After all, it's not a problem that you can filter a for loop in a comprehension but not anywhere else, is it?

And it's not like there would be any confusion. If someone wants to know "how do I write a lambda function in a list", the answer is just "write lambda: spam(x)", not "you can't do it".

However…

>    f(***whatever***)


That one seems like the easiest to dismiss—after all, you can, and should, use keyword arguments whenever it improves clarity—but it turns out to be the most serious problem. First, many of the key higher-order functions, even after the recent arg clinic work, still don't take keyword arguments—like almost everything in itertools. Second, many of these functions take a predicate first, meaning you have to keyword everything if you want to keyword that. And at that point, I think you lose all the benefits. Compare:

    takewhile(lambda x: x<5, a)
    takewhile(predicate(x)=x<5, iterable=a)

In fact, even in cases where there aren't later parameters, compare:

    defaultdict(lamdba: [])
    defaultdict(default_factory()=[])

I think in both cases, the second one gains little or nothing in clarity in exchange for its verbosity. So, it's not really true that you can always just use a keyword. Which means the benefit of the feature overall may be too limited. I'm digging through examples, and so far, sorting keys and Tkinter callbacks are the only cases I've found that are improved (even assuming you accept the basic premise, which I know you personally don't).


More information about the Python-ideas mailing list