Why not real anonymous functions?

Thanks, I understand it can be hard to find the history of these things. It’s usually safe to assume that any idea related to syntax that other languages have has been brought up before though.

Yes, it’s still relevant. Just as all the other previous discussions on any idea are.

Python’s lambda functions ARE anonymous functions. So what precisely are you asking for? Isn’t it a way to make lambda functions able to do things they can’t currently do? Usually that’s described as “multi-line lambdas” because the existing lambda functions are restricted to a single expression, although that term is slightly inaccurate as technically an expression CAN go across multiple lines, and what people really want is “lambdas that contain statements”. But “multi-line lambdas” is close enough.

2 Likes

The current lambda is a particular implementation of anonymous functions. It is possible to imagine implementing anonymous functions in a way that does not build on the current lambda implementation at all. However every proposal and consequently every objection seems to assume that what we need is to extend the current lambda implementation to support mutliple statements (as you say, “multi-line” is not precise enough, but that does appear to be the terminology).

I’ll double down on this point, as it is the crux of my original question: where have anonymous functions been proposed? I genuinely don’t see anywhere that someone has said “let’s add real anonymous functions to Python”. Truly I expected to find a rejected PEP. At least part of my question is: why is there not even a PEP for this?

I’m slightly frustrated because everyone here seems to be aware of some deep history on this topic. But as a relative outsider there’s very little official documentation on something that seems like a major potential benefit to the language. It would be perfectly reasonable to expect to see a PEP outlining why Python can’t/won’t do this. But there is no such thing; just a variety of arcana about why “multi-line lambdas” won’t work.

What is the difference between “real anonymous functions” and a lambda that can support multiple statements? I’m confused about what distinction you’re making there.

2 Likes

We’re all confused as to what “real anonymous functions” means. I suspect that nobody’s ever proposed them before because they’ve all used different words to describe their proposals.

2 Likes

The difference would be purely syntactic. You could imagine a few different constructs (not necessarily proposing either of these as a real solution, just examples):

my_func = (*args, **kwargs) => 
    do_some_stuff()
    do_some_other_stuff()

another_func = def(*args, **kwargs):
    do_some_stuff()
    do_some_other_stuff()

The fundamental problem here seems to be with properly delineating the function. I imagine that is the major objection to any kind of solution (including one that involves the existing lambda keyword). But it’s not insurmountable; there are clearly some other design considerations or preferences driving these objections.

If the difference is purely syntactic then there’s no difference. The historical objections are not just about syntax! So you’re back to reading discussions about this from 18 years ago

2 Likes

I’m sorry but referencing discussions from 18 years ago, while providing relevant context, does nothing to answer the question of whether Python should consider adding anonymous functions today. This is exactly the point I made above where everyone here seems to be saying “We’ve always done it this way”.

I seem to remember a post in one of these threads (not sure if on this forum or python-ideas mailing list) from A. Coghlan who showed how Ruby blocks are a convenient and versatile construct.
That post was more thought-provoking that short requests for multi-expression lambdas (or in-expression defs).

3 Likes

The point that lots of people have been trying to make is that it is on you to respond to the objections in that discussion. You can’t say “well that discussion is old enough to vote so I don’t need to read it”. It is not anyone else’s responsibility to re-enact a historical discussion just so that you can participate in it, nor does anyone have to summarize it for you. You’re proposing the feature, you have to justify it.

Brett Cannon wrote a relevant blog post a couple days years ago [1]. Everyone here is devoting time to an open-source project out of kindness, and no one should expect anything from anyone else. Even people who are just procrastinating while they wait for some long processes to finish[2] are here because they want to help other people and improve the ecosystem. But that doesn’t mean they work for free.


  1. edit: he posted a link to it recently, my mistake ↩︎

  2. as a hypothetical example, not specifically anyone in this discussion <_< ↩︎

5 Likes

That’s a really interesting idea and I suppose it solves the delimiter problem by making it explicit. But that also seems like a heavy lift since it potentially requires introducing multiple new keywords.

So one of the reasons the answer is still “no” is because you’re not actually offering a concrete proposal. Nothing will ever happen unless someone makes an actual, implementable, proposal. And defends it against whatever objections people have, even if those are along the lines of “what about this issue raised 15 years ago?”

So if you have a specific proposal that defines a syntax for “real anonymous functions”[1] then by all means present it. The answer may still be “no”, but maybe it won’t.

But to answer the question “why not real anonymous functions” in isolation - “because no-one has written a proposal that hasn’t been rejected yet”.

Does that help?


  1. I still think you’re just splitting hairs by distincuishing these from multi-line lambdas, but that’s just terminology ↩︎

2 Likes

Your response is clear and helpful. Thank you.

Now I am curious. I wonder what the appetite would be for some kind of keyword-based delimiter, along the lines of Ruby blocks as mentioned by @merwok.

The point of the previously linked blog post was for Guido to explain that in his opinion finding unambiguous syntax was not the problem with multi-line lambda functions. Rather the problem was (and still is) whether it is actually a good thing to allow arbitrarily complicated functions to be included inline as part of larger expressions.

There are some cases where a simple lambda function is nice and readable because the function is so simple that seeing the expression in the lambda conveys its meaning more clearly than any name could. If the function has many lines and is included as part of an expression then it is likely complex enough that giving it a name would be better.

In the example code everything is trying to fit into one statement:

this_one_takes_a_func_arg(
    "foo",
    42,
    (*args, **kwargs) => (
        """Does useful and interesting things, I promise"""
    ),
)

I would prefer to see the code like this:

def do_interesting_things(*args, **kwargs):
    """Does useful and interesting things, I promise"""

this_one_takes_a_func_arg("foo", 42, do_interesting_things)

Now the code in the body of do_interesting_things stands on its own and can be indented like normal Python code. Meanwhile the expression where the function was passed has become much clearer and fits all on one line. The code for both the function and the expression where the function is used will likely become clearer by being separated like this. It is for example much easier to see how many arguments are being passed in the function call.

In future if more code needs to be added to the body of the function then the expression with the inline function would become messier and harder to read. The restriction of lambda functions to a single expression helps to prevent this by drawing a clear line around when the inline function is becoming too complicated and should rather be factored out as an ordinary named function.

4 Likes

The official list archives:

The Python-list Archives
The Python-ideas Archives
Mailman 3 Python-Dev - python.org

Unfortunately, the first two cannot be directly searched, but python-list was linked to a google group which google indexes for web searches. Not sure about the other two.

Many of the discussions included non-lambda syntax proposals.

The points you seem to have missed are:

  1. Anonymous functions are a bit defective, as I partially explained in my previous post. But you are not really asking for anonymous functions. To get that, we would just need to make the name part of def statements optional. But this would be useless as there would be no usable reference to the new function and it would be deleted. So you are really asking for function expressions that result in a reference that can be passed, returned, otherwise used to call the function. For this purpose, the __name__ attribute of the function is irrelevant. While lambda expression functions are anonymous in the sense of not being bound to any name in any namespace, they do have the __name__ attribute <lambda>. The same would be done
    with any alternate syntax.

  2. Lambda expressions within a loop seem to be more more bug-prone than equivalent def statements outside the loop. My guess is that people are less apt to see that function code situated within a loop body is disconnected from the rest of the loop than when the same function code is somewhere output the loop in a def statement. It is easy to think the same for any expression syntax.

  3. If one wants the full power and flexibility of def statements, the easiest thing to do is to use a def statement, nested or otherwise. Learning an alternate syntax to do the same is an extra burden. Even restricted lambda statements are an extra learning chore.

  4. Python is quite intentionally a statement and expression language, not an expression-only language like Lisp, which is where possibly anonymous function expressions came from. It does not need every statement fully duplicated as expressions. Like the function code in lambda expressions, the conditional code in conditional expressions is restricted to expressions, not a suite of statements. Comprehensions are similarly equivalent to loop statements with a restricted loop body, in particular newlist.append(item), newset.add(item), newdict.__setitem__(key, value) or yield item. In all these cases, if you want the full expressive power of the statement form, a sensible answer is to use the statement form.

8 Likes

I recall this, too. It’s probably [Python-ideas] An Alternate Suite Delineation Syntax For Python? (was Re: [Python-Dev] [PATCH] Adding braces to __future__), but I thought it was a longer post. I’m probably mis-remembering.

2 Likes

The official list archives:

The Python-list Archives
The Python-ideas Archives
Mailman 3 Python-Dev - python.org

This version of Python-ideas is searchable.

A quick search gave me this thread which in turn links to 3 other threads with similar proposals.
This should give @drdavella a good starting point for reviewing some of the arguments against it.

That eventually leads to this comment, which I think sums up the major problem, that being one of syntax. I know people will disagree, but for me, if the syntax problem were resolved, then I’d welcome “expressions that produce functions consisting of multiple statements”, commonly called multi-line lambdas.

But without a solution to the syntax issue, the whole argument is not worth having.

5 Likes

For me, it’s not so much the syntax of such an expression itself, but how well mutli-line anything fits in the expected use-case, as an argument to a function.

Given that most functions that could be defined with lambda expressions are probably still too big to be stuffing into the argument list of a function call, I’m still skeptical as to how useful these would be in practice.

We can already define multiple-line string literals, but I’ve rarely if ever seen anything like

some_function(x, """This is
a long string
to embed in a function call.""", y)

Even ignoring something like

some_function(x,
              """This is
                 a long string
                 to embed in a function""",
              y)

and accepting that a multi-line lambda would have more tolerance for additional indentation (beyond what we could remove from the string above with textwrap.dedent), I have trouble imagining a syntax that would address this for me.

1 Like

Agreed. If someone can come up with a workable syntax, there’s some value in discussing the merits of anonymous functions as a language construct. If we don’t have a syntax, though, any such discussion is theoretical at best, and most likely a waste of everyone’s time.

2 Likes