[Python-ideas] Multi Statement Lambdas

Vladimir Filipović hemflit at gmail.com
Sun Oct 21 17:04:02 EDT 2018


On Sun, Oct 21, 2018 at 6:39 PM Chris Angelico <rosuav at gmail.com> wrote:
> Sure, but can you give examples where you can't use lambda, but still
> want it to have no name?

I can try kinda answering this:
It's less with everyday built-ins and the standard library (though see
first example below), and more with libraries and frameworks that want
callbacks (or callables in general) passed in.

Sometimes I need that callable to be something very simple, but it
technically can't be a lambda because it has a statement in it.
Defining it as a function forces me to give it not only a name, but a
place too. Defining it just before the point of use is a natural
location in one sense, but it makes the visual flow of the code worse,
especially if I need to make several such steps (with different
almost-lambdas) in a row.


>From the standard library, I can actually think of Thread:

t1 = Thread(target=(lambda: counter += 1))
t2 = Thread(target=(lambda: sum += current_quux()))

Because they include statements, it needs to be:

def inc_counter():
    counter += 1
t1 = Thread(target=inc_counter)
def update_sum():
    sum += current_quux()
t2 = Thread(target=update_sum)


>From one popular library:

ws = websocket.WebSocketApp(
    url,
    on_open = (lambda ws: ws.send('subscribe'); conn_counter += 1),
    on_message = (lambda ws, msg: print(msg); msg_counter += 1))

Because they include statements, I again need to create those
functions separately. Naming isn't so much a problem here, but it
would turn kludgey if I needed to make several such calls in the same
scope.

In any case, that's a common little frustration I often put up with. I
think most other languages around Python's power level don't make that
a problem.


To expand that argument a bit, lambdas have access to names in their
immediate context that can be more of a pain with less-local
functions. For a toy example:

[(lambda a: print(x + a)) for x in l]

When print was a statement, defining this lambda as a named function
would have had to use more arguments. The richer the context, the more
noise it would have added.



BTW, don't treat the above `(lambda: stmt)` syntax as a _proposal_ per se, BUT:

No matter what we allow inside a lambda, from the outside it's an expression.
How do we make a Python expression span multiple lines? In simplified
terms, we put it in parentheses.
How do we separate an expression whose boundaries would be ambiguous
in a given context (e.g. a tuple literal inside a parameter list)? We
put it inside a pair of parentheses.
Hmm.

I mean, these already work:

(lambda: 2
    + 3)

lambda: 2 + (
    3)

They're multi-LINE lambdas, just not multi-statement (or even uni-statement).

If Python _was_ to somehow allow statements inside lambdas at all at
some point in the future (which I don't expect), I don't see that that
would then need any additional special syntax for multi-line-ness or
for separating them from the surrounding context.


More information about the Python-ideas mailing list