A simple proposal concerning lambda

Here's what I call a simple proposal. Some people might find it outrageous. Today is not 1st April. BACKGROUND ============ Many Python users don't like the name lambda. But many Python users don't want any change here. This is true because there are millions of Python users, and even 100 is many. And it's hard to introduce a new keyword, which might break existing code. (And perhaps even worse, break the community.) https://wiki.python.org/moin/LocalUserGroups
There about 1,637 Python user groups worldwide in almost 191 cities, 37 countries and over 860,333 members.
SOME VALID PYTHON ================== Here's some valid Python, defining two functions fn and gn, that are virtually identical.
Notice that fn and gn have the same type, and differ by name.
And that we can modify the display name of fn and gn.
MY SIMPLE PROPOSAL ==================== Here is my simple proposal. Enhance Python to allow
MIGRATION ========== Migration of code would require only a keyword substitution of 'lambda' by 'def'. And in the docs 1. Note that 'def' can mean 'define' (the current use), and also 'defer' (evaluation of an expression). 2. In the first case, we have a *named function*. In the second case, we have an *expression function*. This idea came to me while writing: https://mail.python.org/pipermail/python-ideas/2018-August/052880.html -- Jonathan

I'm trying to dig up past threads about alternatives to lambda because I would be astonished if "def" hadn't been considered and rejected for some reason. What I've found so far is this unreassuring post from Guido back in 2006 <https://mail.python.org/pipermail/python-dev/2006-February/060415.html> On Tue, Aug 21, 2018 at 4:27 PM, Jonathan Fine <jfine2358@gmail.com> wrote:

Hi Abe Summary: You've done good work here. I've skim read the 2006 discussion you found. You wrote:
[Python-Dev] Let's just *keep* lambda https://mail.python.org/pipermail/python-dev/2006-February/060415.html
This is an excellent piece of work. I'm most grateful. Here's what Guido said:
I've quickly read through the posts that followed Guido's message, picked out the ones that interest me. Here's a list.
And one of the messages had a link to still live and excellent page
This page lists over 100 suggestions, mostly variants. So far as I can see, my simple proposal isn't listed on that page. The page also says
The word 'deferred' appears 7 times on the page. It also appears in the python-dev messages. If someone with more time and less bias then myself were to summarise this discussion from 2006, I'd be most grateful, and they'd have material for a great blog post. Finally, many thanks to Abe for finding this gem, and countless people's hard work in keeping it alive to be found. Backwards compatibility is there for a reason. -- Jonathan

I don't think this change makes sense, but if it's done, there should be another change, with actual implications: There is no way to express the types of the parameters in a lambda - `lambda x: int : x` is obviously a syntax error. Replacing the colon with a different symbol, such as "=>" will make this possible: def x => x def x: int => x def x: int -> int => x It will also give one less meaning to the colon. Elazar On Tue, Aug 21, 2018 at 6:28 PM MRAB <python@mrabarnett.plus.com> wrote:

Le 22/08/2018 à 04:12, MRAB a écrit : this is a great idea. To me, someone who understands the following 2 lines: lambda x, y: x * y def a(x: float, y: int) -> float: ... would probably understand the following: lambda(x: float, y: int) -> float: x * y (more type hints, I like it!)

[Jonathan Fine]
Awesome! Unfortunately the links to conversations seem to all be broken! Most of the links are from December 2004, so I pulled up the discussion for that month <https://mail.python.org/pipermail/python-list/2004-December/subject.html#sta...> and searched "lambda" I was able to find what I believe is reference [1]: https://mail.python.org/pipermail/python-list/2004-December/264515.html It looks like the post numbers got mangled... Anyway, it looks like that page covers December 2004-June 2005, I found a few nuggets of opposition: https://mail.python.org/pipermail/python-list/2004-December/247348.html https://mail.python.org/pipermail/python-list/2004-December/273038.html I sort-of understand the opposition to multi-line anonymous functions, but I think the Terry Reedy (in the second link) is a bit too dismissive of the concept of anonymous functions. I don't work with user-interfaces a lot, but when I do; I can see why UI coders use anonymous functions so much. Defining a function in a statement can be far less expressive and far more noisy than in an expression. It's like: I'll tell you my solution, but first let me shave this Yak here. You're defining often one-off functions before describing what you're going to use it for. It's only after you actually pass them to an event-watcher that the context of their logic is clear. For instance:
vs.
# lack of noisy preamble to your code ui_element.on_mouseover(<what to do> with event)
The anonymous function is given meaning by virtue of the context in-which it's defined.

Abe Dillon writes:
IIRC, early drafts of PEP 3000 (the PEP that was the planning document for the Python 3 project) removed lambda altogether. However there was strong opposition, so we ended up keeping lambda. Some of those discussions morphed to ideas about "improving" lambda. So you may find discussions of lambda in threads titled "PEP 3000" or "Python 3000". -- Associate Professor Division of Policy and Planning Science http://turnbull.sk.tsukuba.ac.jp/ Faculty of Systems and Information Email: turnbull@sk.tsukuba.ac.jp University of Tsukuba Tel: 029-853-5175 Tennodai 1-1-1, Tsukuba 305-8573 JAPAN

On Tue, Aug 21, 2018 at 10:27:20PM +0100, Jonathan Fine wrote:
Here is my simple proposal. Enhance Python to allow
hn = def a, b=2, c=3: a ** b / c
Enhancements ought to allow us to write new code that we couldn't do before, or open up new kinds of algorithms that weren't easy or possible before. This is a mere cosmetic change, replacing a perfectly valid keyword with one which clashes with an existing keyword in what I consider to be an ugly way. While we're at it, perhaps we ought to replace: - "else" with "otherwise" ("else" is a weird word, outside of programming we hardly ever use it without a leading "or") - "import" with "load" (shorter) - "for" with "repeat with" (I've always found it awkward that the word "for" sounds like an number) - "raise" with "throw" - and most importantly, "def" with "fun", which will have the advantage of making Python programming more fun! Admittedly these run into backwards-compatibility issues, which your suggestion does not. But if we're going to break people's code by changing keywords, let's do it properly! *wink* Changing the public API of a language, its keywords, is not something to be done lightly. The consequences of such a change can include: - breaking backwards compatibility; - code churn (people have to "fix their code" even if it wasn't broken); - confusion ("what's the difference between def anonymous functions and lambda anonymous functions?"); - more to learn during the transition (sometimes code uses lambda, sometimes def, so you need to know both) - more documentation explaining why the name is only sometimes needed; - more unit tests etc to ensure the feature works correctly, e.g. to test for the syntax error when people use def unanonymously when they should use it anonymously: map(def func(a, b, c): a+b-c, zip(seq1, seq2, seq3)) Those costs are real and should only be paid when the benefits outweigh the costs. In this specific case, there's also a very real cost: - you will *seriously annoy and frustrate* those of us who like lambda and dislike the look of "def" inside expressions; - while only *slightly pleasing* those who have already learned lambda but don't like it. They've already learned the existing word, now they have to unlearn it. And the corresponding benefit is tiny: - The conceptual difficulties with lambda is not the word but the concept of anonymous functions as first class values; that doesn't change, so no benefit there. - One less keyword in the language (after the transition period). - Two fewer keystrokes. - but "def" is still jargon that needs to be learned. (Does it mean defeat, defame, defer, defend, or that thing bears do in the woods? To a non-English speaker, memorising "def" = "define" is no less obscure than memorising "lam" = "lambda" would be for English speakers.) I don't think this cosmetic change comes even close to the break-even point of costs versus benefits. Maybe if we were designing Python from scratch today, there would be a good argument to be made for using def in both the statement and expression form, but even that's not a sure thing. Changing it *now* is more costly with less benefit. To give an example of a problematic keyword where changing it is not just cosmetic, for many years, consider the "for...else" statement. It seems to be saying: run the for loop *or else* run this block but that's not what it actually means. But even if we had consensus that the "else" keyword should be changed (to what? "then" is my suggestion), the benefit is probably too small to disrupt the Python ecosystem by actually making that change. By the way, I'll also point out that the way you have demonstrated the use of anonymous functions is considered a (mild) abuse of syntax. Your example: # reverting back to lambda for the moment hn = lambda a, b=2, c=3: a ** b / c ought to be written as: def hn(a, b=2, c=3): return a ** b / c which ensures that hn has a nice name for debugging. Lambdas ought to be limited to in-place uses, as part of a larger expression and not just an assignment, probably 99% of the time. Hence: results = map(lambda a, b=2, c=3: a ** b / c, sequence) widget.register(callback=lambda: spam.eggs()) are reasonable examples of how one might find lambdas in the wild. Replacing the keyword: results = map(def a, b=2, c=3: a ** b / c, sequence) widget.register(callback=def: spam.eggs()) Doesn't look so attractive now, I wager. Using "def" inside an expression looks strange. And this looks outright disturbing: def method(self, arg, callback=def arg: arg+1): pass -- Steve

[Steven D'Aprano]
most importantly, "def" with "fun", which will have the advantage of making Python programming more fun!
I'm sold. Make the change and SHIP IT! No need for committee approval. [Steven D'Aprano]
If we're going to break people's code by changing keywords, let's do it properly! *wink*
I'm not backing this proposal, but I am curious what the proposal could break. [Steven D'Aprano]
- Two fewer keystrokes.
THREE!!! [Steven D'Aprano]
- but "def" is still jargon that needs to be learned.
It already has to be learned and it's already associated with function declaration. [Steven D'Aprano]
Yeah, that's pretty much my take on the matter. That ship sailed way back when Py3k was finalized. [Steven D'Aprano]
for-finished? for-done? for-stopped? # referencing StopIteration for-anything_but_else? [Steven D'Aprano]
Oh, come-on; D'Aprano! That was just to demonstrate properties of the resulting object. It's not meant to be production code. [Steven D'Aprano]
Eh... I think they look fine. Which is worse: def method(self, arg, callback=def arg: arg+1): pass or lambda arg, callback=lambda arg: arg+1: None because the second one makes me go cross-eyed... On Tue, Aug 21, 2018 at 8:55 PM, Steven D'Aprano <steve@pearwood.info> wrote:

On Wed, Aug 22, 2018 at 12:48 PM, Abe Dillon <abedillon@gmail.com> wrote:
If you have a use-case for a lambda function that takes a callback and has a default value for that callback, please submit it to The Daily WTF. In Steve's example, the main function was created with a statement. ChrisA

On Wed, Aug 22, 2018 at 12:57 PM, Abe Dillon <abedillon@gmail.com> wrote:
True, but hardly significant. The one inside lambda is local to it. Though... it's insignificant when the function header precedes the expression/body. With the proposal to move the header to the end, that might become problematic, which makes it yet another cost to the proposal. ChrisA

[Chris Angelico]
I don't think it would be a problem because, like ternary and other circuiting operations, the expression isn't evaluated until certain criteria are met. The arrangement shouldn't matter. ...I think. On Tue, Aug 21, 2018 at 10:10 PM Chris Angelico <rosuav@gmail.com> wrote:

I wrote:
Here is my simple proposal. Enhance Python to allow
hn = def a, b=2, c=3: a ** b / c
I'd like to add a clarification. Here are two proposals. ONE. Wherever you could have used 'lambda', you now have a choice. You can still use 'lambda', or you can use 'def' instead. The semantics are unchanged. TWO. Wherever you could have used 'lambda', you must now use 'def' instead. The semantics are unchanged. I'm proposing ONE, not TWO. All existing Python code will continue to run exactly as before. No Python code will have to be changed. And no new programming capabilities would be added. So why do it? In a nutshell, to remove an obstacle. To make DEFerred expressions easier to understand. Is it worth doing? That's a cost-benefit analysis. I think the main benefit will be in the docs, and in teaching people Python. And does it fit in with the Zen of Python?
There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch.
So is having both 'def' and 'lambda' unpythonic? Two ways to do the same thing! With PEP 572 (see exceptional cases), the following are equivalent:
a = 1 (a := 1)
And we're allowed to use tabs or spaces for indentation (see PEP 666). So *maybe* having both 'lambda' and 'def' is sufficiently Pythonic. -- Jonathan

I've often thought the same about "lambda." Although I've long since gotten used to the word, "def" without a function name seemed like a better choice, especially for beginners. +0.25 for proposal ONE However, parentheses should be allowed and lambda put on a long deprecation schedule. -Mike On 2018-08-22 08:58, Jonathan Fine wrote:

Let me stand up and say that I personally like lambda. It's the standard terminology and not easily confused. I doubt that "many Python users" have a problem with it. Evidence? I dislike the def proposal strongly. It is too similar to a normal def. At least get a new keyword then Some other languages: lambda: scheme, lisp \ : Haskell fn : Standard ml function : JavaScript [] : C++ Stephan Op wo 22 aug. 2018 18:16 schreef Mike Miller <python-ideas@mgmiller.net>:

On Wed, Aug 22, 2018 at 9:51 AM, Stephan Houben <stephanh42@gmail.com> wrote:
Let me stand up and say that I personally like lambda. It's the standard terminology and not easily confused.
I agree. And secondly, even if I didn't like it, changing the name of something because it's a slightly less confusing name to newbies is a really low priority! If you look back at previous discussion, the real push was to exp[and lambda's capabilities -- maybe allow more than one expression, or ??? But that would make it MORE confusing to newbies, not less. I actually think it makes a strikes a pretty good balance -- to use the idiomatic phrase :-) -CHB -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker@noaa.gov

I think it would have been better to use def from the start instead of lambda. The only thing JS does right is using the same "function" keyword for both of these. However, changing it now doesn't seem that important to me. (And I've used lambda's as default argument - I was moving data from one database to another, and wanted a generic method to switch out column names that defaulted to the same header. So it became a lambda x:x function by default, but you can provide any function that takes and returns a string and change the column names. This was last week.) And lets be real - adding a new keyword is something to be done extremely sparingly. lambda could have been avoided by re-using def. And no, it being the same keyword is an advantage, as they do the exact same - they create a function. It's the same reason as we use if condition:

Op do 23 aug. 2018 09:06 schreef Jacco van Dorp <j.van.dorp@deonet.nl>:
Seriously? Consider how the following code function f() { return 42; } may or may not bind the function to f, depending on if it appears in expression or statement context. Just Google and find all the newbies who get confused about this. And the proposed def syntax is almost as terrible: def greet: print("hello'') This would then be legal, and leave the newbie confused why greet remains undefined. Please don't repurpose def. Repurposing for and if inside comprehensions is already confusing to newbies. Stephan

Op do 23 aug. 2018 om 09:40 schreef Stephan Houben <stephanh42@gmail.com>:
The only thing I seriously think they did better is exact keyword choice. Nothing else. So an expression def would still be def <ARGS>:<EXPR>, like it is with lambda now. JS remains a clusterfuck of terrible choices, as you can tell by the existence of http://www.jsfuck.com/ . An alternative livible solution to your def greet would be to require parens around the parameter list. Nobody would take the following for a statement: def (greet):print("hello") (Also, you could conceivably drop the colon, which might make some people happy who care about the 1001 uses that a colon has in python. ) I also believe I explicitly advocated against making changes now, just saying that it might have been a better idea at some point in the past.

On Wed, Aug 22, 2018 at 04:58:17PM +0100, Jonathan Fine wrote:
And add a new obstacle: "What's the difference between function expressions created with def and function expressions created with lambda?" "Nothing." "So why do I have to learn TWO sets of syntax for exactly the same thing?" "Because its easier than learning one!"
To make DEFerred expressions easier to understand.
They're not "deferred expressions", they're functions. It is true that function bodies contain deferred expressions (or statements), but the whole is not the part. -- Steve

On Tue, Aug 21, 2018 at 09:57:51PM -0500, Abe Dillon wrote:
I picked the example to showcase an example of where this suggested new syntax looks bad. Part of debating proposals is to look at pros and cons, not just to look at the best cases. But it wasn't an engineered example in the sense of "invented just for this purpose". Of course I used metasyntactic variables rather than real code, but I assure you I have real code that uses lambda in function parameter lists. Nor am I the only one. For example, I have a private module (fortunately now retired) that backports itertools to older versions of Python, and it includes a version of groupby that looks like this: class groupby(object): def __init__(self, iterable, key=lambda obj: obj): ... I, er, "borrowed" a Prime number sieve class from somewhere (and forget where, so I can't give credit where credit is due) and it starts like this: class Primes(object): def __init__(self, n=None, extend=False, exf=lambda x:x + x//2): The std lib contains a test that this correctly raises SyntaxError: def f(*, x=lambda __debug__:0): pass (the problem here is that __debug__ cannot be used as a parameter name). So its not just me who uses lambda as a default argument.
Why would you use 'arg' for both the argument to the method and the callback! That's at least a little WTF.
Heh, I didn't even notice that. It certainly wasn't intentional. Sorry. -- Steve

I'm trying to dig up past threads about alternatives to lambda because I would be astonished if "def" hadn't been considered and rejected for some reason. What I've found so far is this unreassuring post from Guido back in 2006 <https://mail.python.org/pipermail/python-dev/2006-February/060415.html> On Tue, Aug 21, 2018 at 4:27 PM, Jonathan Fine <jfine2358@gmail.com> wrote:

Hi Abe Summary: You've done good work here. I've skim read the 2006 discussion you found. You wrote:
[Python-Dev] Let's just *keep* lambda https://mail.python.org/pipermail/python-dev/2006-February/060415.html
This is an excellent piece of work. I'm most grateful. Here's what Guido said:
I've quickly read through the posts that followed Guido's message, picked out the ones that interest me. Here's a list.
And one of the messages had a link to still live and excellent page
This page lists over 100 suggestions, mostly variants. So far as I can see, my simple proposal isn't listed on that page. The page also says
The word 'deferred' appears 7 times on the page. It also appears in the python-dev messages. If someone with more time and less bias then myself were to summarise this discussion from 2006, I'd be most grateful, and they'd have material for a great blog post. Finally, many thanks to Abe for finding this gem, and countless people's hard work in keeping it alive to be found. Backwards compatibility is there for a reason. -- Jonathan

I don't think this change makes sense, but if it's done, there should be another change, with actual implications: There is no way to express the types of the parameters in a lambda - `lambda x: int : x` is obviously a syntax error. Replacing the colon with a different symbol, such as "=>" will make this possible: def x => x def x: int => x def x: int -> int => x It will also give one less meaning to the colon. Elazar On Tue, Aug 21, 2018 at 6:28 PM MRAB <python@mrabarnett.plus.com> wrote:

Le 22/08/2018 à 04:12, MRAB a écrit : this is a great idea. To me, someone who understands the following 2 lines: lambda x, y: x * y def a(x: float, y: int) -> float: ... would probably understand the following: lambda(x: float, y: int) -> float: x * y (more type hints, I like it!)

[Jonathan Fine]
Awesome! Unfortunately the links to conversations seem to all be broken! Most of the links are from December 2004, so I pulled up the discussion for that month <https://mail.python.org/pipermail/python-list/2004-December/subject.html#sta...> and searched "lambda" I was able to find what I believe is reference [1]: https://mail.python.org/pipermail/python-list/2004-December/264515.html It looks like the post numbers got mangled... Anyway, it looks like that page covers December 2004-June 2005, I found a few nuggets of opposition: https://mail.python.org/pipermail/python-list/2004-December/247348.html https://mail.python.org/pipermail/python-list/2004-December/273038.html I sort-of understand the opposition to multi-line anonymous functions, but I think the Terry Reedy (in the second link) is a bit too dismissive of the concept of anonymous functions. I don't work with user-interfaces a lot, but when I do; I can see why UI coders use anonymous functions so much. Defining a function in a statement can be far less expressive and far more noisy than in an expression. It's like: I'll tell you my solution, but first let me shave this Yak here. You're defining often one-off functions before describing what you're going to use it for. It's only after you actually pass them to an event-watcher that the context of their logic is clear. For instance:
vs.
# lack of noisy preamble to your code ui_element.on_mouseover(<what to do> with event)
The anonymous function is given meaning by virtue of the context in-which it's defined.

Abe Dillon writes:
IIRC, early drafts of PEP 3000 (the PEP that was the planning document for the Python 3 project) removed lambda altogether. However there was strong opposition, so we ended up keeping lambda. Some of those discussions morphed to ideas about "improving" lambda. So you may find discussions of lambda in threads titled "PEP 3000" or "Python 3000". -- Associate Professor Division of Policy and Planning Science http://turnbull.sk.tsukuba.ac.jp/ Faculty of Systems and Information Email: turnbull@sk.tsukuba.ac.jp University of Tsukuba Tel: 029-853-5175 Tennodai 1-1-1, Tsukuba 305-8573 JAPAN

On Tue, Aug 21, 2018 at 10:27:20PM +0100, Jonathan Fine wrote:
Here is my simple proposal. Enhance Python to allow
hn = def a, b=2, c=3: a ** b / c
Enhancements ought to allow us to write new code that we couldn't do before, or open up new kinds of algorithms that weren't easy or possible before. This is a mere cosmetic change, replacing a perfectly valid keyword with one which clashes with an existing keyword in what I consider to be an ugly way. While we're at it, perhaps we ought to replace: - "else" with "otherwise" ("else" is a weird word, outside of programming we hardly ever use it without a leading "or") - "import" with "load" (shorter) - "for" with "repeat with" (I've always found it awkward that the word "for" sounds like an number) - "raise" with "throw" - and most importantly, "def" with "fun", which will have the advantage of making Python programming more fun! Admittedly these run into backwards-compatibility issues, which your suggestion does not. But if we're going to break people's code by changing keywords, let's do it properly! *wink* Changing the public API of a language, its keywords, is not something to be done lightly. The consequences of such a change can include: - breaking backwards compatibility; - code churn (people have to "fix their code" even if it wasn't broken); - confusion ("what's the difference between def anonymous functions and lambda anonymous functions?"); - more to learn during the transition (sometimes code uses lambda, sometimes def, so you need to know both) - more documentation explaining why the name is only sometimes needed; - more unit tests etc to ensure the feature works correctly, e.g. to test for the syntax error when people use def unanonymously when they should use it anonymously: map(def func(a, b, c): a+b-c, zip(seq1, seq2, seq3)) Those costs are real and should only be paid when the benefits outweigh the costs. In this specific case, there's also a very real cost: - you will *seriously annoy and frustrate* those of us who like lambda and dislike the look of "def" inside expressions; - while only *slightly pleasing* those who have already learned lambda but don't like it. They've already learned the existing word, now they have to unlearn it. And the corresponding benefit is tiny: - The conceptual difficulties with lambda is not the word but the concept of anonymous functions as first class values; that doesn't change, so no benefit there. - One less keyword in the language (after the transition period). - Two fewer keystrokes. - but "def" is still jargon that needs to be learned. (Does it mean defeat, defame, defer, defend, or that thing bears do in the woods? To a non-English speaker, memorising "def" = "define" is no less obscure than memorising "lam" = "lambda" would be for English speakers.) I don't think this cosmetic change comes even close to the break-even point of costs versus benefits. Maybe if we were designing Python from scratch today, there would be a good argument to be made for using def in both the statement and expression form, but even that's not a sure thing. Changing it *now* is more costly with less benefit. To give an example of a problematic keyword where changing it is not just cosmetic, for many years, consider the "for...else" statement. It seems to be saying: run the for loop *or else* run this block but that's not what it actually means. But even if we had consensus that the "else" keyword should be changed (to what? "then" is my suggestion), the benefit is probably too small to disrupt the Python ecosystem by actually making that change. By the way, I'll also point out that the way you have demonstrated the use of anonymous functions is considered a (mild) abuse of syntax. Your example: # reverting back to lambda for the moment hn = lambda a, b=2, c=3: a ** b / c ought to be written as: def hn(a, b=2, c=3): return a ** b / c which ensures that hn has a nice name for debugging. Lambdas ought to be limited to in-place uses, as part of a larger expression and not just an assignment, probably 99% of the time. Hence: results = map(lambda a, b=2, c=3: a ** b / c, sequence) widget.register(callback=lambda: spam.eggs()) are reasonable examples of how one might find lambdas in the wild. Replacing the keyword: results = map(def a, b=2, c=3: a ** b / c, sequence) widget.register(callback=def: spam.eggs()) Doesn't look so attractive now, I wager. Using "def" inside an expression looks strange. And this looks outright disturbing: def method(self, arg, callback=def arg: arg+1): pass -- Steve

[Steven D'Aprano]
most importantly, "def" with "fun", which will have the advantage of making Python programming more fun!
I'm sold. Make the change and SHIP IT! No need for committee approval. [Steven D'Aprano]
If we're going to break people's code by changing keywords, let's do it properly! *wink*
I'm not backing this proposal, but I am curious what the proposal could break. [Steven D'Aprano]
- Two fewer keystrokes.
THREE!!! [Steven D'Aprano]
- but "def" is still jargon that needs to be learned.
It already has to be learned and it's already associated with function declaration. [Steven D'Aprano]
Yeah, that's pretty much my take on the matter. That ship sailed way back when Py3k was finalized. [Steven D'Aprano]
for-finished? for-done? for-stopped? # referencing StopIteration for-anything_but_else? [Steven D'Aprano]
Oh, come-on; D'Aprano! That was just to demonstrate properties of the resulting object. It's not meant to be production code. [Steven D'Aprano]
Eh... I think they look fine. Which is worse: def method(self, arg, callback=def arg: arg+1): pass or lambda arg, callback=lambda arg: arg+1: None because the second one makes me go cross-eyed... On Tue, Aug 21, 2018 at 8:55 PM, Steven D'Aprano <steve@pearwood.info> wrote:

On Wed, Aug 22, 2018 at 12:48 PM, Abe Dillon <abedillon@gmail.com> wrote:
If you have a use-case for a lambda function that takes a callback and has a default value for that callback, please submit it to The Daily WTF. In Steve's example, the main function was created with a statement. ChrisA

On Wed, Aug 22, 2018 at 12:57 PM, Abe Dillon <abedillon@gmail.com> wrote:
True, but hardly significant. The one inside lambda is local to it. Though... it's insignificant when the function header precedes the expression/body. With the proposal to move the header to the end, that might become problematic, which makes it yet another cost to the proposal. ChrisA

[Chris Angelico]
I don't think it would be a problem because, like ternary and other circuiting operations, the expression isn't evaluated until certain criteria are met. The arrangement shouldn't matter. ...I think. On Tue, Aug 21, 2018 at 10:10 PM Chris Angelico <rosuav@gmail.com> wrote:

I wrote:
Here is my simple proposal. Enhance Python to allow
hn = def a, b=2, c=3: a ** b / c
I'd like to add a clarification. Here are two proposals. ONE. Wherever you could have used 'lambda', you now have a choice. You can still use 'lambda', or you can use 'def' instead. The semantics are unchanged. TWO. Wherever you could have used 'lambda', you must now use 'def' instead. The semantics are unchanged. I'm proposing ONE, not TWO. All existing Python code will continue to run exactly as before. No Python code will have to be changed. And no new programming capabilities would be added. So why do it? In a nutshell, to remove an obstacle. To make DEFerred expressions easier to understand. Is it worth doing? That's a cost-benefit analysis. I think the main benefit will be in the docs, and in teaching people Python. And does it fit in with the Zen of Python?
There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch.
So is having both 'def' and 'lambda' unpythonic? Two ways to do the same thing! With PEP 572 (see exceptional cases), the following are equivalent:
a = 1 (a := 1)
And we're allowed to use tabs or spaces for indentation (see PEP 666). So *maybe* having both 'lambda' and 'def' is sufficiently Pythonic. -- Jonathan

I've often thought the same about "lambda." Although I've long since gotten used to the word, "def" without a function name seemed like a better choice, especially for beginners. +0.25 for proposal ONE However, parentheses should be allowed and lambda put on a long deprecation schedule. -Mike On 2018-08-22 08:58, Jonathan Fine wrote:

Let me stand up and say that I personally like lambda. It's the standard terminology and not easily confused. I doubt that "many Python users" have a problem with it. Evidence? I dislike the def proposal strongly. It is too similar to a normal def. At least get a new keyword then Some other languages: lambda: scheme, lisp \ : Haskell fn : Standard ml function : JavaScript [] : C++ Stephan Op wo 22 aug. 2018 18:16 schreef Mike Miller <python-ideas@mgmiller.net>:

On Wed, Aug 22, 2018 at 9:51 AM, Stephan Houben <stephanh42@gmail.com> wrote:
Let me stand up and say that I personally like lambda. It's the standard terminology and not easily confused.
I agree. And secondly, even if I didn't like it, changing the name of something because it's a slightly less confusing name to newbies is a really low priority! If you look back at previous discussion, the real push was to exp[and lambda's capabilities -- maybe allow more than one expression, or ??? But that would make it MORE confusing to newbies, not less. I actually think it makes a strikes a pretty good balance -- to use the idiomatic phrase :-) -CHB -- Christopher Barker, Ph.D. Oceanographer Emergency Response Division NOAA/NOS/OR&R (206) 526-6959 voice 7600 Sand Point Way NE (206) 526-6329 fax Seattle, WA 98115 (206) 526-6317 main reception Chris.Barker@noaa.gov

On 22/08/18 17:59, Chris Barker via Python-ideas wrote:
Jonathan isn't proposing to change the name, just to add a synonym. The obvious quote from the Zen at this point is: "There should be one-- and preferably only one --obvious way to do it." -- Rhodri James *-* Kynesim Ltd

I think it would have been better to use def from the start instead of lambda. The only thing JS does right is using the same "function" keyword for both of these. However, changing it now doesn't seem that important to me. (And I've used lambda's as default argument - I was moving data from one database to another, and wanted a generic method to switch out column names that defaulted to the same header. So it became a lambda x:x function by default, but you can provide any function that takes and returns a string and change the column names. This was last week.) And lets be real - adding a new keyword is something to be done extremely sparingly. lambda could have been avoided by re-using def. And no, it being the same keyword is an advantage, as they do the exact same - they create a function. It's the same reason as we use if condition:

Op do 23 aug. 2018 09:06 schreef Jacco van Dorp <j.van.dorp@deonet.nl>:
Seriously? Consider how the following code function f() { return 42; } may or may not bind the function to f, depending on if it appears in expression or statement context. Just Google and find all the newbies who get confused about this. And the proposed def syntax is almost as terrible: def greet: print("hello'') This would then be legal, and leave the newbie confused why greet remains undefined. Please don't repurpose def. Repurposing for and if inside comprehensions is already confusing to newbies. Stephan

Op do 23 aug. 2018 om 09:40 schreef Stephan Houben <stephanh42@gmail.com>:
The only thing I seriously think they did better is exact keyword choice. Nothing else. So an expression def would still be def <ARGS>:<EXPR>, like it is with lambda now. JS remains a clusterfuck of terrible choices, as you can tell by the existence of http://www.jsfuck.com/ . An alternative livible solution to your def greet would be to require parens around the parameter list. Nobody would take the following for a statement: def (greet):print("hello") (Also, you could conceivably drop the colon, which might make some people happy who care about the 1001 uses that a colon has in python. ) I also believe I explicitly advocated against making changes now, just saying that it might have been a better idea at some point in the past.

On Wed, Aug 22, 2018 at 04:58:17PM +0100, Jonathan Fine wrote:
And add a new obstacle: "What's the difference between function expressions created with def and function expressions created with lambda?" "Nothing." "So why do I have to learn TWO sets of syntax for exactly the same thing?" "Because its easier than learning one!"
To make DEFerred expressions easier to understand.
They're not "deferred expressions", they're functions. It is true that function bodies contain deferred expressions (or statements), but the whole is not the part. -- Steve

On Tue, Aug 21, 2018 at 09:57:51PM -0500, Abe Dillon wrote:
I picked the example to showcase an example of where this suggested new syntax looks bad. Part of debating proposals is to look at pros and cons, not just to look at the best cases. But it wasn't an engineered example in the sense of "invented just for this purpose". Of course I used metasyntactic variables rather than real code, but I assure you I have real code that uses lambda in function parameter lists. Nor am I the only one. For example, I have a private module (fortunately now retired) that backports itertools to older versions of Python, and it includes a version of groupby that looks like this: class groupby(object): def __init__(self, iterable, key=lambda obj: obj): ... I, er, "borrowed" a Prime number sieve class from somewhere (and forget where, so I can't give credit where credit is due) and it starts like this: class Primes(object): def __init__(self, n=None, extend=False, exf=lambda x:x + x//2): The std lib contains a test that this correctly raises SyntaxError: def f(*, x=lambda __debug__:0): pass (the problem here is that __debug__ cannot be used as a parameter name). So its not just me who uses lambda as a default argument.
Why would you use 'arg' for both the argument to the method and the callback! That's at least a little WTF.
Heh, I didn't even notice that. It certainly wasn't intentional. Sorry. -- Steve
participants (13)
-
Abe Dillon
-
Brice Parent
-
Chris Angelico
-
Chris Barker
-
Elazar
-
Jacco van Dorp
-
Jonathan Fine
-
Mike Miller
-
MRAB
-
Rhodri James
-
Stephan Houben
-
Stephen J. Turnbull
-
Steven D'Aprano