Re: [Python-ideas] Syntactic sugar to declare partial functions

I'd rather have functools.partial() to be added as a new method on function objects.
Would become: add_2 = add.partial(2) Nothing to change on the parser, no obscure syntax for future readers, and we can get the opportunity of rewriting partial() in C as right now it is amazingly way, way slower than a lambda.

I'd like to push for the less jargon-y `func.given()` version if this gains traction. Not only is it shorter, it's a much more common term with a clear meaning. Words like 'partial', 'curry', 'lambda', and 'closure' are fine for text books, published papers, and technical discussion, but I think they would (or do in the case of 'lambda') harm Python. I know the correct term for the 'if-else' expression is a 'ternary' expression, but that doesn't mean Python should have used the word 'ternary' in the syntax. On Thu, Aug 9, 2018 at 12:14 PM, Neil Girdhar <mistersheik@gmail.com> wrote:

I prefer partial since many programmers studied computer science, and also it makes the concepts easier to google. Anyway, I don't actually want either a partial member nor new syntax for this, but if I had to choose, I'd choose no new syntax. On Thu, Aug 9, 2018 at 2:32 PM Abe Dillon <abedillon@gmail.com> wrote:

On Thu, Aug 09, 2018 at 01:32:00PM -0500, Abe Dillon wrote:
It's a clear, *generic* meaning that doesn't have any association with partial application. https://www.google.com/search?q=function+given We'd be trying to create that association from scratch.
Words like 'partial', 'curry', 'lambda', and 'closure' are fine for text books, published papers, and technical discussion,
And programmers. Programming is a technical skill with its own jargon. Classes, inheritence, exceptions, trampolining, processes, threads, protocols, imports, decorator, builders... we are happy with all those, why should we fear partial and lambda?
but I think they would (or do in the case of 'lambda') harm Python.
That's an extreme overreaction. Do you mean to imply that there are people who looked at Python, loved the language, but decided to use something else because they didn't like the choice of the keyword "lambda"? If not, in what way is Python harmed? Would it be faster if the keyword was "function", or use less memory, or more expressive? Remember that to millions of programmers in the world, "function" is just as much an obscure foreign piece of jargon they have to memorise as "lambda" is to English-speakers. -- Steve

[Neil Girdhar]
I prefer partial since many programmers studied computer science
Many did not. I studied electrical engineering and wouldn't have been able to tell you what the word 'partial' meant four years ago even though I've been programming in one form or another since the late nineties. Many programmers are scientists, engineers, financial analysts, etc. I'm pretty sure I know what a closure is or what currying is, but if you put me on the spot, I'd probably turn to Wikipedia to make sure I don't screw up the definition. [Neil Girdhar]
It makes the concepts easier to google.
That can be an important criteria, but it can also be a red-herring. If an implementation is clear enough, few people would have to google it. If, however, you use obscure enough words like "lambda", people will google it every day and still find it confusing. The ternary expression is difficult to google if you don't know the jargon "ternary", but there's less of a need to google it because it's pretty obvious how it works based simply on its implementation. [Steven D'Aprano]
Sure, that's a good point. I don't think that sounds like such a big problem, but I also don't hate 'partial'. I just prefer 'given'. At any rate, I don't find the google-ablilty argument super strong because there are many constructs that are difficult to google, but still pretty great (e.g. comprehensions). [Steven D'Aprano]
Yes, technical discussion among programmers. [Steven D'Aprano]
I get that programming carries it's own jargon and I understand that it has a beneficial function. It can facilitate concise communication of nuanced concepts. It can also be a needlessly confusing way to convey otherwise simple concepts. In the latter case, it can feel like the intent is to create an air of superiority through esoteric language. I feel like "curry" and "lambda" are needlessly un-descriptive and confusing. "partial" really isn't that bad, I just prefer "given" because I think it's pretty clear. I've never heard of "trampolining", but if I had to guess: it's probably related to recursion that involves more than one function? I suspect that most programmers couldn't describe the difference between a type and a class. I suspect that most programmers couldn't tell you the difference between an exception or an error. I know that lots of programmers refer to the "__init__" method as a "constructor" instead of an "initializer". Precision is less of a problem In a programming language. `func.given` doesn't have dozens of possible meanings. It's meaning has to be completely unambiguous to the machine. [Steven D'Aprano]
Extreme? I thought it was a rather benign opinion. I'm not exactly frothing at the mouth here. It's not like I'm declaring holy war on Python for using the word 'lambda'. I just think it was a mistake (and thatdeath should come to all non-believers). [Steven D'Aprano]
No. Not at all. Is that what you got out of my sentence? Am I really the one being extreme? [Steven D'Aprano]
If not, in what way is Python harmed? Would it be faster if the keyword was "function", or use less memory, or more expressive?
I didn't realize I'd hit such a nerve. I think there are better ways that anonymous functions could have been implemented. I've already said in past discussions, I think the expression should come before the signature because the signature is often obvious from context so placing it before the logic is kinda noisy. I don't know what the best syntax would have been, but I refuse to believe that an esoteric word from an esoteric branch of calculus with an arbitrary etymology was the absolute best choice available. I think the harm that choice caused is relatively minor, but I don't think it was a great choice. I'm truly sorry if I hurt your feelings. [Steven D'Aprano]
Maybe we should use Egyptian Hieroglyphs then. Even the playing field. It doesn't matter anyway, right? It's all nonsense to someone... Honestly, I don't think 'partial' is that bad. I just wanted to support your own comment: although possibly a less jargon name would be nicer:
add1 = add.given(1)
But you seem to have some grudge against me. I don't get all the outrage over what I thought was a fairly benign post. Did I do something to make you so angry at me? I'd like to resolve whatever it is instead of having to deal with this every time I post. On Fri, Aug 10, 2018 at 2:09 AM, Steven D'Aprano <steve@pearwood.info> wrote:

On Fri, Aug 10, 2018 at 6:21 PM Abe Dillon <abedillon@gmail.com> wrote:
Not that it matters, but comprehension is a standard term in mathematics and computer science apparently: https://en.wikipedia.org/wiki/List_comprehension https://en.wikipedia.org/wiki/Set-builder_notation
I didn't think you were being extreme at all. I think you're making a reasonable point about keeping things simple. I disagree with you though when it comes to avoiding the technical terms. It's easier for people new to a field to learn the jargon of that field than it is to try to make it easier for them and by essentially creating a whole lot more technical jargon. (Even if that jargon uses common words.) Your idea for "given" isn't obviously doing a partial function application. Someone might wonder if "given" is setting thread local storage, or setting attributes on a callable class, or opening context managers at call time…

[Neil Girdhar]
https://en.wikipedia.org/wiki/List_comprehension https://en.wikipedia.org/wiki/Set-builder_notation
The point I was trying to make is: If you were to read a set comprehension for the first time, not knowing what it was, what would you google? It's not an easily searchable construct, but it's still an elegant, fairly easy to comprehend feature. This is actually a pretty good example of where I stand. Of course we use words like 'comprehensions' when talking about language features, partly because it's easier than "that expression that builds a list, set, or dictionary" and partly because we often discuss how other languages implemented the same general feature. That doesn't mean that the syntax has to contain the word 'comprehension': make_initials = lambda person: "".join(generator(domain=person.names, predicate=bool, term=lambda name: name[0])) initials = list.comprehension(domain=people, predicate=lambda person: any(person.names), term=make_initials) Borrowing from math notation and/or jargon, as comprehensions do, is fine, especially if it's common enough to be taught in grade-school. Set-builder notation is beyond what I learned in grade-school, but Python does more than 'borrow' from set builder notation. It uses familiar words like "for", "in", and "if", in place of that little epsilon (∈) and bar and logical conjugation operator (*∧*) which I think help make them understandable. [Neil Girdhar]
I'm willing to concede that that's probably true in this case. I think the term "partial function application" is fairly clear rather than jargon-for-jargon's sake. I could see someone thinking it meant that the function is partially run, but that's a pretty minor worry. I'm sure without looking it up, people would assume all sorts of things about what func.given could mean. I also think the case of someone running into either usage without some pretty glaring context clues about what's going on is pretty unlikely. I won't concede that lambda was an optimal choice. Even a reuse of the keyword "def" would have been better because it would clearly relate it to function declaration: hand = sorted(pocket + community, key=def card: card.suit)[-5:] It's literally short for "define function", so it makes sense. My other complaint about lambdas, that they should be arranged logic first, does go against pretty much all other implementations of anonymous functions <https://en.wikipedia.org/wiki/Anonymous_function#Examples>, but I still think it makes more sense: hand = sorted(pocket + community, key=card.suit from card)[-5:] There are several possible variations of that concept. I think most of them would be better than the current syntax. An alternate form of lambda is probably never going to come and I'm OK with that. It's just my go-to anti-jargon example. Anonymous functions are not a confusing concept, yet people get caught up on it surprisingly frequently. I think the name is partly to blame. On Fri, Aug 10, 2018 at 5:42 PM, Neil Girdhar <mistersheik@gmail.com> wrote:

Answering a few of Abe's comments out of order... On Fri, Aug 10, 2018 at 05:20:25PM -0500, Abe Dillon wrote:
Have we become so sensitive to disagreement that criticism of ideas is immediately seen as "angry", "a grudge", "outrage"? If so, I find that sad and worrying. My feelings aren't hurt, you haven't hit a nerve, I'm not angry at anything you wrote, and I'm not holding a grudge. I thought we were discussing *ideas*, not attacking each other. Just because I challenge your statements doesn't mean I'm attacking you. Moving on... [...]
I suspect that most programmers couldn't describe the difference between a type and a class.
In Python, there is none. There is a sense in which types are different from classes, but that sense is not fundamental, and in practice many languages blur the lines between them.
I suspect that most programmers couldn't tell you the difference between an exception or an error.
There's a school of thought that most programmers can't program. https://blog.codinghorror.com/why-cant-programmers-program/ But regardless, we don't design Python based on the misunderstandings of the least competent, most ignorant demographic. That's why we have exceptions, only some of which are errors, and not StopIterationError KeyboardInterruptError SystemExitError etc. I believe that using a well-designed language should gently encourage the programmer to learn, by example. I didn't know the the functional programming techniques of map, reduce or partial until I came across them in Python. I think I'm a better programmer and less ignorant now than I was for that. Consequently, when I hear you describing how few programmers know the term "partial", what I think is "what a great opportunity for them to learn something new!". Or not, of course. For those of us who don't care for functional programming idioms, there's no need to use partial in our own code.
Yes, that's what I got out of your sentence. If you don't mean that, I don't know what you do mean. You've said that the choice of keyword, "lambda", has caused harm. Given the chance to clarify what you meant, you stood by your comment that the choice of keyword "lambda" has done real, significant, non-trivial harm to Python (the language, or the community). Presumably you fear the same thing will happen again if we choose "partial" (otherwise, why raise the issue?). Harm in what sense? That's what I tried to ask earlier, perhaps not as clearly as I intended. If the choice of name "lambda" doesn't repel would-be users, or cause bugs, or harm performance, then what harm does it do? This is a genuine question. I'm trying to understand your comments, not just dismiss them. You made a comment much stronger than merely "I don't like the name", claiming that the name is harmful. I could just dismiss your comment as meaningless hyperbole and ignore it, but I thought to give you the respect of assuming that you might be correct but I just wasn't understanding why. Hence my question.
No, we ought to stick to ASCII, for reasons I've discussed recently in other threads. And Python does have a long-standing tradition of sticking to mostly English words, a tradition for which I personally am grateful. But we ought to "check our privilege", as they say. I think that if we as a community automatically reject any word because it isn't "plain English", that would be a sign of unexamined privilege and quite rude to boot. How can we insist that 3/4 of the world learn English words to use Python, if we aren't even willing to move out of our own comfort zone to the extent of learning accurate jargon terms from our own profession? None of this is to rule out "given". (I think it's certainly better than Perl's choice of "assuming".) But if we go down this path (which is by no means decided!), and choose "given" over "partial", we ought to be clear about the reasons why. -- Steve

[Steven D'Aprano]
Just because I challenge your statements doesn't mean I'm attacking you.
No. Telling me I'm having an extreme overreaction means you're attacking me. Pushing the narrative that I'm irrational by enumerating the least charitable interpretations of my words possible then claiming you were just discussing *ideas* is disingenuous. I don't know who you think you're kidding, Steven. You could have simply asked me what I meant. It would have been much easier. All those extra words serve a very clear purpose and everyone knows it, so you can stop acting "sad and worried" when someone calls you out. I explained my position on lambda as fully as I care to in my response to Niel if you care to read it. I only think lambda harms Python in so far as there were better alternatives that communicate their intention much better and are more readable. That's an opinion. If you must know, i'm not currently frothing at the mouth as I state it. My original post was agreeing with you. Supporting your own words. If you don't agree with my position that we should avoid jargon for jargon's sake, then what exactly did you mean when you said, "although possibly a less jargon name would be nicer?" Can you articulate why you think it might be nicer to use a less jargon name? What about my saying it all of a sudden makes it an "extreme overreaction"? [Steven D'Aprano]
What are you talking about? I explained exactly what I meant: I think there are better ways that anonymous functions could have been
Notice: I never said "real, significant, non-trivial harm" anywhere in this entire discussion. I never said anything close to that. Stop jamming bullshit in my mouth to suit your narrative that I'm "extremely overreacting". It's not cute. [Steven D'Aprano]
This is a genuine question. I'm trying to understand your comments, not just dismiss them.
If you're so genuinely interested, then how come you couldn't be bothered to read my explaination above? [Steven D'Aprano]
Presumably you fear the same thing will happen again if we choose "partial" (otherwise, why raise the issue?).
There is no issue. I've already conceded that. Please read the conversation that followed with Neil Girdhar. I was simply stating a preference and trying to articulate my reasoning behind that preference. My whole intent was to +1 your alternative and say "I prefer given to partial". That's it. [Steven D'Aprano]
Python does have a long-standing tradition of sticking to mostly English words, a tradition for which I personally am grateful.
I am too. I'd like that to continue. [Steven D'Aprano]
Rude? Who would it be rude to if we had chosen "anonfunc" instead of "lambda"? [Steven D'Aprano]
How can we insist that 3/4 of the world learn English words to use Python
Do you really think that 3/4 of the world learns English just to write Python? Do you think the only english they learn are the built-ins and standard library of Python? English is a dominant language in business and programming. That statement is no more "privileged" than the statement that the US Dollar is the most popular global reserve currency. It's a fact that I have no control over. [Steven D'Aprano]
...if we aren't even willing to move out of our own comfort zone to the extent of learning accurate jargon terms from our own profession?
Very few of us are computer scientists by profession. That's not even where 'lambda' comes from. In computer science, it's called an "anonymous function". "lambda" comes from lambda calculus. [Steven D'Aprano]
I gave my reasons: it's shorter and less jargon while remaining fairly clear (in my opinion) You've already claimed that "possibly a less jargon name would be nicer", so I don't see the fuss. Apparently it's extreme when I say it. On Sun, Aug 12, 2018 at 8:06 PM, Steven D'Aprano <steve@pearwood.info> wrote:

He is questioning the concept that the lambda keyword has caused any harm. You assert that it caused minor harm. Minor harm can still be real, significant, and non-trivial. Has the keyword choice done any harm aside from mailing list jamming, and forum posts. I believe he is asserting that it hasn't. The burden of proof would be on you that it has caused any level of harm to the language of community, the criteria being that the harm be real, significant (if minor) and non-trivial. You will find no evidence to support your argument. You might find evidence that functional programming techniques are less useful with anonymous functions in python due to the restriction to only use expressions, but that isn't what is being argued.

On Mon, Aug 13, 2018 at 1:31 PM, Abe Dillon <abedillon@gmail.com> wrote:
If your reaction was extreme, saying so isn't attacking you.
Explain, please, what the HARM is that comes from the use of the word "lambda". In contrast, using the word "function" does definitely have harm, because you can no longer use the name "function" as a variable or parameter. Also, the signature is most decidedly NOT obvious from context, nor is it insignificant. Putting it first gives context to the body of the function. Python made the correct choice here.
No, but it's no less jargonny.
https://en.wikipedia.org/wiki/Anonymous_function "In computer programming, an anonymous function (function literal, lambda abstraction, or lambda expression) is a function definition that is not bound to an identifier." So... I would say "lambda" is very firmly connected with anonymous functions. ChrisA

[Alex Walters]
What, exactly, is the difference between "minor" and "non-trivial" and when did I say the harm was "significant and non-trivial"? [Alex Walters]
You will find no evidence to support your argument.
You could read what I wrote to Neil Girdhar who was able to engage with me without implying that I've lost my mind. [Chris Angelico]
If your reaction was extreme, saying so isn't attacking you.
Is this a hypothetical now? I said "*I think* they would (or do in the case of 'lambda') harm Python." I wasn't aware the word "harm" was something only deranged maniacs use. [Chris Angelico]
Explain, please, what the HARM is that comes from the use of the word "lambda".
I HAVE. [Chris Angelico]
Also, the signature is most decidedly NOT obvious from context
Who decided this? It's been decided by some committee? When you write a key function, you don't know how many arguments are going to be passed? [Chris Angelico]
nor is it insignificant.
I never said it was. I just said that the logic is more important from the standpoint of the reader. [Chris Angelico]
Putting it first gives context to the body of the function. Python made the correct choice here.
I disagree. This forum is looking more and more toxic. I've explained myself over and over again. I just wanted to +1 Steven's original comment. This is ridiculous. I guess I've pissed of the good-old-boys by calling out Steven's unnecessary condescension. Great. It looks like Python is in fantastic hands. On Sun, Aug 12, 2018 at 10:50 PM, Chris Angelico <rosuav@gmail.com> wrote:

On Mon, Aug 13, 2018 at 2:56 PM, Abe Dillon <abedillon@gmail.com> wrote:
lst.onselect = anonfunc(print(target_item)) What's target_item? If you can't see the signature and see that it's a parameter, you should look externally for it. What are the parameters to an onselect function? Doesn't that seem important enough to see the signature up front? It's not just *how many* arguments are being passed. It's what they're called, too. You cannot interpret the body of a function without knowing that. Hiding that off to the end would make the language worse, not better. Plus, can you name any similar language that does that? Every other language I can think of has the parameters before the body. While this isn't a clinching argument by any means (Python has a different argument order for the ternary if operator, for instance), it's indicative. ChrisA

[Chris Angelico]
If you're not even going to read the explanation I've already given, then I have no reason to respond. Your example looks nothing like what I've suggested and this whole conversation is being derailed by your need to win the argument. On Mon, Aug 13, 2018 at 12:04 AM, Chris Angelico <rosuav@gmail.com> wrote:

Now that the discussion has officially devolved into something that has absolutely nothing to do with the original topic, I'd like to point out something: (Note that I have no affiliation with the managers of this mailing list at all and am just posting this as an outsider.) In Steven D'Aprano's original message, I didn't see anything there as being a personal attack or as having an angry tone, at least based on his normal posting style. Maybe a bit critical and stern, but not really personal. You may have interpreted it as that, but I seriously doubt it was the intention. I'd like to propose an alternative to Hanlon's razor, the Internet razor: Never attribute to malice that which is adequately explained by lack of context in online conversations. Online, there is no tone of voice, facial expressions, or extra context to really help distinguish intent. Misinterpreting has been a classic issue that's been around for ages and has only gotten worse. When writing a message, we're responsible for ensuring that the intent is clearly portrayed. When reading a message, we're responsible for correctly interpreting such intent, and everyone is usually better off if, when in doubt, the interpretation leans towards ambiguity over malice. On Sun, Aug 12, 2018, 11:57 PM Abe Dillon <abedillon@gmail.com> wrote:
-- Ryan (ライアン) Yoko Shimomura, ryo (supercell/EGOIST), Hiroyuki Sawano >> everyone else https://refi64.com/

it becomes "toxic" only after off-topic. fine list needs just a reminder from time to time ! Abdur-Rahmaan Janhangeer https://github.com/Abdur-rahmaanJ Mauritius

I don't really want to get involved in this, but I feel like everyone is piling up on Abe unfairly. On Mon, Aug 13, 2018 at 1:14 AM Ryan Gonzalez <rymg19@gmail.com> wrote:
When Abe wrote just this: "but I think they would (or do in the case of 'lambda') harm Python" — which is nothing but an opinion. We're all welcome to our opinions without having to prove them like lawyers. Steve replied this: "That's an extreme overreaction. Do you mean to imply that there are people who looked at Python, loved the language, but decided to use something else because they didn't like the choice of the keyword "lambda"? If not, in what way is Python harmed? Would it be faster if the keyword was "function", or use less memory, or more expressive?" To my perhaps tender Canadian ears, that is incredibly abrasive. Steve could have just explained why he felt differently without slamming Abe's opinion as "an extreme overreaction" and then diving into a set of rhetorical questions that assume an extreme reading of Abe's statement. Now, as you say, this is Steve's usual posting style. But new people don't know him. I also found him quite abrasive when I started posting here, but then I noticed that it's not personal and he treats everyone this way. There are some great posters here, and I like to read python-ideas because I learn so much from them: Nick, Antoine, Brett, and Nathaniel to name a few, but there are many more. I think it's important for newcomers to try to be respectful, but it's also important to treat newcomers with the same kindness you would treat a guest in your home. Best, Neil

On Sun, 12 Aug 2018 23:56:24 -0500 Abe Dillon <abedillon@gmail.com> wrote:
My experience is that this forum was toxic almost from the start, because it encourages people to engage into the kind of behaviour you are witnessing now (i.e. largely pointless and semi-agressive nit-picking which sometimes feels straight out of the well-known Argument Clinic sketch). Regards Antoine.

On Mon, 13 Aug 2018 at 11:30, Antoine Pitrou <solipsis@pitrou.net> wrote:
IMO, things have got worse over time. As a forum explicitly designed for discussing speculative ideas, the general tone has become less and less sympathetic towards people (particularly newcomers, which is especially unfortunate) expressing ideas which are, shall we say, less than perfectly thought through. I'm OK with gently pointing out to a poster that they will need to tighten up their arguments and assertions as the discussion progresses towards a concrete proposal, but that's not how things feel any more. In particular there seems to be an extremely aggressive dislike of anything that seems like "opinion" which can't be backed up with solid evidence. Certainly we don't expect proposals based purely on subjective opinion to make it through to implementation, but we shouldn't be holding the process of exploring ideas to such rigorous standards. Anyway, I won't say any more, as I don't really know how we could change things. And yes, a lot of the above is my view, and is subjective. Asking me to provide evidence and back up my assertions sort of proves my point, so please treat it as just that, my opinion, and take it or leave it on that basis. Paul

What I feel we lack are better tools for checking bad behavior and nudging people in the right direction, apart from having discussions like this. Temporarily locking threads that have become heated comes to mind. As do temporary bans for rowdy members. As does closing threads that have ceased to serve any good purpose. These things would have been pretty handy in several recent and heated discussions, including the PEP 505 one I participated in a couple of weeks ago. How much of this is possible on a mailing list? I don’t know. But I remember a year or two ago there was a proposal to move python-ideas to a different format, perhaps a Discourse forum or similar, which would provide some handy administration tools and other UX improvements. That discussion, ironically, was beset by some of the very animosity that better tooling would help control. (And I learned a bit about email etiquette and top-posting...) Maybe we need to revive that discussion? Overall, I don’t think we have a people problem on this list as much as we have an administration tooling problem.

normally at above 20+ posts it gets crazy Abdur-Rahmaan Janhangeer https://github.com/Abdur-rahmaanJ Mauritius

This is a half-baked thought, but perhaps a sub-reddit would facilitate better moderation and we'd get the bonus of threaded discussions and a side-bar for ediquite and other important info. I know Reddit has a mixed reputation, but some of the best moderated subs like /r/science and /r/neutralpolitics have fantastic discussions. We could open /r/pythonideas and see if it gains traction. We also have the skill set to write a pretty good moderation bot. On Mon, Aug 13, 2018, 12:11 PM Michael Selik <mike@selik.org> wrote:

some mods warnings or reminders might also help ! Abdur-Rahmaan Janhangeer https://github.com/Abdur-rahmaanJ Mauritius

Cleaning out the Ccs, presumably subscribed. Nicholas Chammas writes:
I would go further, and say that use of the word says more about those who used it than about the list.
I disagree. I think this is a scale problem: we have too many people posting, some of them new or infrequent, to prevent (1) people getting triggered by one word in an otherwise excellent post and going off in their replies, (2) intemperate rebuttals to the replies in (1), or (3) interminably long threads sustained by people who don't yet know when not to post. If (1) and (2) can be solved by moderation, then you pretty much have a toxic channel. The best solution to (3) is not channel-wide moderation, but killing/ muting the thread or specific posters in your MUA. If you're going to participate in channels as high-traffic as the Python lists, and still try to hold down a day job, this is one of the very few features where I'm willing to say "bite the damn bullet and get a REAL MUA!" It really improves life. If most people have muted the thread, there's little to no harm in letting those who still care continue. This also has the advantage that you don't have to wait for a thread to be of use to nobody to kill it. You can do that now!
PEP 505 was an example of none of the above as far as I can see, though. I think it's tough to find places where you could invoke a thread freeze or a poster ban and not get a storm of pushback. And it's kinda hard to see how killing a thread on an open PEP is useful.
How much of this is possible on a mailing list?
Poster bans, whether temporary or indefinite, are possible. Thread freezing or closing are in principle possible, but they'd be really annoying to posters due to the nature of email, I suspect (posts would bounce and clutter up your inbox later, rather than having the "post reply" function disabled in the UI). Nor are they implemented in GNU Mailman, although spam-checking could probably be coerced to serve (ban messages where In-Reply-To or References contains recent IDs in the frozen/closed thread). This would require some additional scripts for efficient admin, and MUA tooling to extract References would be nice, but all that doable in an afternoon or two.
Going back to that discussion now that Guido is less involved might get you a different answer. (He was not a fan of Discourse, and while he told me he likes Zulip at PyCon Cleveland, he also said he sees it as independent of the function of mailing lists. He also said Mailman 3's HyperKitty forum-like functionality sounds like it will be good enough for him soon enough, so he'd probably be opposed to moving to forum software on the "don't break what don't need fixing" principle. All that is almost moot now.)
Overall, I don’t think we have a people problem on this list as much as we have an administration tooling problem.
That's what @jack says, too. :-/ Sorry, that's a bit too snarky, but the fundamental problem is that *people* post too much. That's a *people* problem even though there are no problem people, and the people that are deciding what to post aren't the admins (unless you'll accept out-and-out censorship, or an editorial board if you prefer a euphemism). So I don't see an admin tooling solution here. Steve -- 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

Hi All Here's something that's at the core of my approach. Faced with this sort of problem, I read again https://www.python.org/psf/codeofconduct/. And then I compare my intentions, words and actions to the guidelines in this, the Python Community Code of Conduct. Only when I have, so to speak, regained my purpose and composure do I consider the conduct of others. At least, this is what I aspire to do. -- Jonathan

I'm perhaps the newest and most ignorant subscriber here - I daresay everyone here has superior python knowledge to me, and all my other computing knowledge is inferior to what I can do with python. (and so far, I've had no influence at all on python) However, this mailing list, generally, does not seem toxic to me at all. I haven't experienced any condescension about my lack of knowledge. While I can acknowledge that there might be superior alternatives to email, I do think the threshold of subscribing and listening in is lower than a lot of other options, like for example subreddits. I for example would have never come if it'd been one of those. 2018-08-14 10:53 GMT+02:00 Jonathan Fine <jfine2358@gmail.com>:

I never said or implied that you lost your mind. Only that you were wrong. It is possible to be wrong and sane. However if you really insist that the two are one in the same... you might actually need to seek out professional help.

On Sun, Aug 12, 2018 at 8:31 PM, Abe Dillon <abedillon@gmail.com> wrote:
Lambda calculus IS computer science. Rejecting lambda as CS is as bad as rejecting the + operator because that's mathematics. I can legitimately argue that + in Python is not the + in mathematics because the Python mathematical operators operate on integers and floats, not real numbers. Therefore we should use a different word like "floatadd". Of course not. Lambda calculus is a model of computation. It was invented about 30 years before the name "computer science" but is nonetheless foundational computer science. If using lambda as a keyword leads people to go and learn about lambda calculus that is a good thing. And as to saying a lambda function is an "anonymous function": the anonymity is not a property of the function. If I assign it to a name, it's no longer anonymous. Really a "lambda" or "lambda function" is just a function, but "lambda" is a synecdoche for "function created with a lambda expression". --- Bruce

On Tue, Aug 14, 2018 at 4:00 AM, Bruce Leban <bruce@leban.us> wrote:
True, but at that point, you get into hairy points of definitions. Which of these functions is anonymous? def do_stuff(callback): ... do_stuff(do_stuff) do_stuff(lambda: 42) do_stuff(callback=lambda: 42) Obviously do_stuff itself has a name. When you pass it a parameter, it can access that as "callback", which means the function has been assigned to a name. Does it cease to be anonymous? What if you use a keyword argument? Within Python, there's a fairly clear definition: if there is something in the source code which sets the function's __name__ attribute, it's not an anonymous function. So anonymous functions come from: * Lambda expressions, always called "<lambda>" * Comprehensions/genexps, always called "<listcomp>" etc * Callable objects that aren't functions (or classes, since those have names) * Maybe something else that I've forgotten. You're absolutely right that a "lambda function" isn't really a thing, in the same way that Python doesn't have "raw strings" (only "raw string literals", which are literals which result in perfectly ordinary strings). But the anonymity of them is a somewhat measurable feature, even if it isn't very important. The distinction between "lambda functions" and "def functions" is important to style guides, but otherwise shouldn't matter. ChrisA

[Bruce Leban]
Lambda calculus IS computer science.
It's a foundation of computer science. That doesn't mean it "IS" computer science. Set theory is a foundation of computer science. It's still it's own discipline. [Bruce Leban]
Rejecting lambda as CS is as bad as rejecting the + operator because that's mathematics.
This is a complete misunderstanding of my argument. Not all programmers are computer scientists. In fact, not all programmers are professional. Many, including myself, came from engineering. Many came from other scientific fields. Many came from finance and all sorts of fields. Many are teenagers who just want to build a cool website or a video game or scrape song lyrics for their favorite bands. The whole point of a programming language is to bridge the gap between machine code and natural language (in Python's case English, as with most other languages). It's to make reading and writing code easier through abstraction, not to create ivory towers through the use of esoteric jargon. It's not supposed to make a cool kids club for people privileged enough to study CS in college. At least that's not my goal. [Bruce Leban]
Yes. I know. [Bruce Leban]
If using lambda as a keyword leads people to go and learn about lambda calculus that is a good thing.
I don't think the point of Python is to force people to eat their vegetables. You might think it's a good thing if everyone learns about Turing machines and the Halting problem and Kolmogorov Complexity and X86 machine code, etc. but that's not what Python is for. I may think that everyone should learn what I learned in college about electromagnetics and semiconductor physics, etc. But I'm not arrogant enough to force that on people who just want to use abstract tools to get some job done. I didn't realize that my distaste for 'lambda' was such an unheard-of opinion. I could have sworn that the likes of Guido Van Rossum and Raymond Hetinger also found the term at least a little troublesome. As someone who has taught Python professionally, I can say that there is a strange mental block regarding lambda expressions. Pretty much every student I've had has struggled with lambda expressions, even those who grasp similarly complex constructs like decorators with ease. This includes students who learned english as a second language. I can only attribute that to the word 'lambda' being confusing as hell. [Bruce Leban]
And as to saying a lambda function is an "anonymous function": the anonymity is not a property of the function.
Yes, It is:
[Bruce Leban]
If I assign it to a name, it's no longer anonymous.
That's not how variable assignment works in Python. The name of the variable doesn't become an attribute of the object assigned to the variable. [Bruce Leban]
My whole point was to be less pedantic, not more pedantic. Pragmatism should prevail over pedantry. This is why, as I've stated earlier, I know that lambda expressions aren't going to change any time soon and I'm fine with that. I consider it a bit of a wart, but whatever. I'm getting really tired of having to defend this opinion. Also, this argument makes no sense. Just because there isn't a way to represent all real numbers in a computer, doesn't mean that integer, floating point, and fractional addition become different kinds of addition. On Mon, Aug 13, 2018 at 1:09 PM, Chris Angelico <rosuav@gmail.com> wrote:

On Tue, Aug 14, 2018 at 5:08 AM, Abe Dillon <abedillon@gmail.com> wrote:
The whole point of a car is to make driving easier through abstracting away the internal details of petrochemical propulsion, but if someone says "I don't want to know about 'gears' or 'brakes' or any of these technical terms", you wouldn't want them driving on the roads you're on. There is a certain level of comprehension that you can't avoid. (If you don't know anything about how to use a car, you can still ride in one, but you can't drive it; and you don't need to understand about anonymous functions in order to operate a computer, but you'll need them to program effectively.)
As someone who currently teaches both Python AND JavaScript professionally, I can say that there is a strange mental block regarding anonymous functions, and it's nothing to do with the word "lambda". In JavaScript, anonymous functions are created with the word "function" (same word as is used for declared functions), and there are just as many points of confusion as there are with Python. ChrisA

[Chris Angelico]
This was originally in response to Bruce Leban's assertion: "If using lambda as a keyword leads people to go and learn about lambda calculus that is a good thing." Are you saying that knowing "what lambda calculus is" is as important to programming in Python as knowing "what breaks are" is to driving? If so, I don't think that analogy holds water. I don't think lambda calculus is fundamental to knowing how to write a program. I don't even think anonymous functions are fundamental to writing a program. I think a programmer could go their whole life without ever knowing what a lambda expression is and still manage to write plenty of very useful code. It seems to me like the whole point of this discussion has turned into getting me to repent and profess my undying love for lambda expressions. I'm sorry to disappoint. Maybe we should split off this discussion into a thread where people can keep badgering me to come up with an objective proof that Python's lambda expressions are not the best implementation possible. Then, at least, we can stop polluting this thread with this tangent. It doesn't seem to matter how many times I try to point this out, but my original comment should be read as: "I like Steven's idea. I prefer `given` to `partial`." I'm sorry I even brought up lambda. I'm truly sorry to all those who wanted to seriously discuss alternatives to functools.partial. On Mon, Aug 13, 2018 at 2:17 PM, Chris Angelico <rosuav@gmail.com> wrote:

On Tue, Aug 14, 2018 at 6:26 AM, Abe Dillon <abedillon@gmail.com> wrote:
No, lambda calculus isn't on par with brakes - but anonymous functions are, and if they're called "lambda", you just learn that. In fact, I would say that the word "lambda" is the least troublesome part of anonymous functions, callbacks, and related topics. It's the same with "partial". Actually, I didn't think of that as "partial application" but as "partial specification of parameters". If you can grok the concept that you can take a function, lock some of its parameters, and get back another function, then you should be able to learn a word to associate with it. ChrisA

Chris Angelico wrote:
No, lambda calculus isn't on par with brakes - but anonymous functions are, and if they're called "lambda", you just learn that.
It's like saying that people would find it easier to learn to drive if "brakes" were called "stoppers" or something. I don't think that's true. -- Greg

On Mon, Aug 13, 2018, 5:48 PM Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
There isn't much jargon involved in learning to drive and most of it is natural: left turn, right turn, blinkers, etc. Compare this with learning to sail. I still don't remember which side is starboard.

On 2018-08-14 02:46, Michael Selik wrote:
<OT> "Starboard" is the side on which was the "steerboard", the large "board" or oar used for steering the boat, a predecessor of the rudder. Most people are right-handed, so it was put on the right-hand side of the boat. Given that, it made sense to tie the boat up to a jetty on its unobstructed left-hand side, the "port" side. Starboard = right, port = left. </OT>

Pedantically, Python's lambda isn't even the same thing as in the lambda calculus. The mathematical abstraction is always curried, and neither Python nor most languages that use the spelling 'lambda' do that. So even assuming users must learn technical vocabulary, this is an inaccurate such term. 'def' or 'func' would be less deceptive here for anonymous functions. The burden of learning the word lambda—and unlearning it's meaning in mathematical logic if you happened to have used that—it's not huge. But it's more than zero. And probably more than leaning 'function'. On Mon, Aug 13, 2018, 8:49 PM Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:

On Tue, Aug 14, 2018 at 7:58 AM, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
Reminds me of this: "So, there's some buttons on the floor. Pedals. Uhh.... That's the "go" pedal... That, I believe, is the stopper... and this... this doesn't do anything...." -- Wreck It Ralph, trying to figure a car out. I'm pretty certain he didn't do any better that way than if he'd used words like "accelerator" and "brake". In fact, this supports my assertion that it's not the terminology that bites you - it's the concepts behind it. Even if he'd known that the other pedal was called the "clutch", it wouldn't have helped him much without knowing how to use it... Whether you spell it "function(arg) {...}" or "lambda arg: ...", it's the semantics that are hardest to learn. ChrisA

The conversation about syntactic sugar for ``functools.partial`` led to a question about whether jargon like "lambda" makes the concept of an anonymous function more difficult to learn. In my own experience teaching, I find that many concepts are easier to introduce if I avoid the Python jargon until after I've explained what it does. This is supported by education research. Some light Googling found a study on the topic [0] that is consistent with my own observations. Picking good names is hard [1]. It's tempting to use terms based on the origin of the concept, historical odds and ends, or even jokes. This can help someone remember the concept when someone is familiar with the origin, history, or joke, but makes the concept more confusing and hard to remember for others. I recommend trying to buck tradition and pick terms that are as simple as possible, requiring the least context to make sense. Jargon can be useful for allowing an expert to quickly identify the context of a term [2]. Plain language phrases can easily create namespace collisions. However, someone searching for or reading about Python concepts already knows that the context is Python programming. Good comparisons can be found in other fields: * Driving -- brakes vs stoppers * Sailing -- starboard vs right-side * Medicine -- postprandial vs after-meal * Biology -- dinosaur vs direlizard In the last case, it turns out direbird might have been a better term. I'm not sure if that supports or detracts from my argument. [0] https://iubmb.onlinelibrary.wiley.com/doi/full/10.1002/bmb.20922 [1] https://martinfowler.com/bliki/TwoHardThings.html [2] https://www.nngroup.com/articles/specialized-words-specialized-audience/ On Mon, Aug 13, 2018 at 9:00 PM Chris Angelico <rosuav@gmail.com> wrote:

On 14/08/2018 20:42, Michael Selik wrote:
While NOT wanting to start another fight I feel that I must put my pedant hat on & point out that the above highlights why domain specific words are used and their specificity actually highlights important concepts, i.e.: * Brakes are used to apply breaking, (i.e. to slow the vehicle, possibly to a stop), while stoppers STOP something. * Starboard = to the right when facing the bow (front of the vessel) not "my right", "your right" or "their right" (which depends on which way you, I & they are facing). * postprandial = after Lunch (not after eating any meal or after a snack). * A dinosaur is specifically an extinct terrible (formerly considered) lizard where as a Gila Monster is definitely a scary & dangerous (dire) lizard. In all of these cases there is a specificity to the word used that is missing from the alternative offered that will, hopefully, be raised by the use of that word. Unfortunately many people, when trying to explain what the word means fail to highlight where it is different (the number of times that I have heard people "explain" port and starboard as left and right without mentioning the word bow or forward is countless). Using a slightly unfamiliar word can cause people to ask, or think about, why this is different & what the difference is while also drawing a parallel that can help the user/student to understand & remember the concept. Also, picking a label for something, and using it consistently, can vastly simplify things like manual searches (or on-line searches). The English language has, historically, always borrowed, co-opted and sometimes perverted words from other languages to allow distinct concepts to be expressed concisely - which I personally, (admittedly as a native speaker), find rather useful. -- Steve (Gadget) Barnes Any opinions in this message are my personal opinions and do not reflect those of my employer. --- This email has been checked for viruses by AVG. https://www.avg.com

Steve Barnes wrote:
* Brakes are used to apply breaking,
I hope they actually apply braking, not breaking. :-)
* A dinosaur is specifically an extinct terrible (formerly considered) lizard
Which technically is not a lizard. -- Greg

Steve Barnes and Greg Ewing wrote:
I can't resist. Puffinus puffinus is the scientific name for (drum roll) no, not the Atlantic (or common) Puffin but (off-pitch fanfare) https://en.wikipedia.org/wiki/Manx_shearwater -- Jonathan

On 15/08/18 06:21, Steve Barnes wrote:
I think you and Michael are arguing to the same end. He was suggesting that it's easier to teach a concept by introducing the idea and then a name for it, rather like the way Python creates objects before binding them. -- Rhodri James *-* Kynesim Ltd

[Michael Selik]
To clarify: The original statement by Steven D'Aprano, "although possibly a less jargon name would be nicer..." indicated to me that he thought there might be situations where less jargon terms are preferable to jargon terms. The argument I tried to make is, "yes I believe there are cases where a less jargon identifier is preferable and that I believe 'lambda' is an example of a missed opportunity to use a less jargon (maybe 'esoteric' is a better word here?), more descriptive name." Subjectively, I don't like lambda expressions. I find the word 'lambda' to be an eye-sore in an otherwise very elegant language. That being said: I believe subjective valuations are rarely devoid of subtle, underlying motivators that are at least grounded in logic if not objective. It's just hard to put your finger on it most of the time. I often try to root out those motivators for why I feel the way I do and articulate them as best I can. At the end of the day, though; I can't always provide a completely objective, logical proof for why I feel the way I do. For instance: when the iPhone was introduced, a lot of people praised it's subjectively "slick" user interface. I believe that perception of slickness is partly because the iPhone emulated physical interfaces very well so it leveraged people's intuition about the physical world. It was delightfully intuitive. I believe that part of my distaste for lambda is that it's an esoteric word that doesn't convey any meaning to someone who's never heard of a 'lambda expression' (which was the case for me when I first encountered it). Even after I had heard of a lambda expression, the fact that the word had little other connection to anything relevant in my brain meant that I had to mentally translate it every time I read for a couple of years. [Steven Barnes]
I don't think this is comparable to calling a car's brakes, "stoppers" for several reasons. 1) What we call something usually relates to how humans communicate to other humans about that thing, not how we actually use the tool. I'm not against the idea of jargon. It clearly serves a useful purpose for humans to communicate to other humans both concisely and with precision. When I tell someone at work that a service went down and they say, "I'll take a look at the logs", I know they're not talking about lengths of cut or fallen tree. I'm glad humans are so good at deducing context that we don't have to constantly disambiguate everything. I also understand that this practice of overloading words sometimes leads to strange results like "currying". Maybe calling it "signature reduction" would have been too unwieldy and/or caused confusion with the word "reduce" which is often used in the same context. None of that has to do with how I interact with a car. Few brake pedals say "brake" on them. I don't have to use the word "brake" to slow down my car. Few of the interfaces in my car even have words. There's no lever that says "high beams". There's no dashboard indicator that says "high beams". I don't have to use the phrase "high beams" to turn on my high beams. At the same time, I don't need to use or know the word "ternary" to read or write a ternary expression in Python. I don't think that was a mistake or a missed opportunity to force people to look up the word "ternary". Sometimes in highly specific contexts, we deal with nuanced concepts like the difference between a parameter and an argument. So we use jargon to distinguish between them. That's not as much of problem in a programming language. The constructs in Python have to have an exact meaning by default. Clearly defining and separating name-spaces is an inescapable fact of life in programming. There's no chance of Python accidentally misinterpreting which "log" you're talking about. There's no potential for a "who's on first" gag <https://www.youtube.com/watch?v=kTcRRaXV-fg>. 2) Cars tend to actually use pretty sensible naming schemes. A windshield shields you from the wind. A windshield wiper wipes the windshield. Windshield wiper fluid is fluid that helps the windshield wiper wipe the windshield, etc. If they called windshield wiper solution "epsilon", it wouldn't cause more crashes or anything, it would just be more confusing than it needs to be. 3) It's not like calling 'brakes' 'stoppers'. It's more like calling an expression that makes a function by some random greek letter. I don't see much need for a metaphor. [Steven Barnes]
* postprandial = after Lunch (not after eating any meal or after a snack).
Not according to Google <https://www.google.com/search?q=postprandial+definition>, Merriam-Webster <https://www.merriam-webster.com/dictionary/postprandial>, Oxford <https://en.oxforddictionaries.com/definition/postprandial>, or Wikipedia <https://en.wikipedia.org/wiki/Prandial>. [Steven Barnes]
I understand the potential benefit of jargon as stated above, but even this isn't always true. Sometimes jargon is created that is counterintuitive and then it just sticks because changing it would be a huge hassle. In electrical engineering, current is supposed to be the "flow of positive charge", but charge conventions were established before we knew how atoms work and learned that positively charged particles don't often move in circuits. Dinosaurs are another good example. Sometimes jargon is a mistake. [Steven Barnes]
It depends on if it's easy to tie said word into a broader understanding. It's easy for me to remember that "agua" means "water" in Spanish because it's very similar to a words that relate to water in english like "aquifer". I have trouble remembering that "izquierda" means "left" because I don't know any word like it. I have to pause and think about it every time without fail! Similarly, I can guess that "anonymous function" means a function without a name, but it took me a while to get used to "lambda" because it was just dangling there with no other connection to its context. Even when I learned about lambda calculus it didn't help much because the "lambda" was an arbitrary choice. There wasn't any way for me to tie it into a richer context. [Steven Barnes]
Also, picking a label for something, and using it consistently, can vastly simplify things like manual searches (or on-line searches).
Yes, Steven D'Aprano mentioned this and it's a fair point. I think it'd have to be pretty horrendous jargon to justify "create [an] association from scratch" as Steven put it. I've since gone back on my original push for "partial" over "given" because I don't think it meets that criteria. I think that "lambda" is a different case because there already existed several better alternatives in other languages and, in the case of "def", in Python itself. [Chris Angelico]
Whether you spell it "function(arg) {...}" or "lambda arg: ...", it's the semantics that are hardest to learn.
Naming and semantics are essentially orthogonal. Sure callbacks and the like can require some painful mental gymnastics, but that's independent of choosing "function" or "lambda". When I talk about students having more trouble learning lambdas than I expect, I'm specifically talking about lambdas, as in:
func = lambda x: x*x
Even students that seemed to quickly grasp functions as first-class objects would stumble on basic lambda expressions. Not as much trouble as callbacks and other, more complex concepts, but more trouble than regular function definition. Anyway, the question should be "Is it always best to use jargon in the implementation of Python features? If so, how do you figure? If not, when and why should it be avoided?" On Wed, Aug 15, 2018 at 12:21 AM, Steve Barnes <gadgetsteve@live.co.uk> wrote:

learn better how to find a compromise (strike a balance) between
Summary: Discussion of the words 'jargon' and 'chatter'. Recommend that we precision and simplicity. This thread is, in part, about the meaning, use and usefulness of words. And 'jargon' is what we are talking about. What is the meaning and use of 'jargon'? According to https://www.etymonline.com/word/jargon (discovered https://en.wikipedia.org/wiki/Jargon) === jargon (n.) mid-14c., "unintelligible talk, gibberish; chattering, jabbering," from Old French jargon "a chattering" (of birds), also "language, speech," especially "idle talk; thieves' Latin" (12c.). Ultimately of echoic origin (compare Latin garrire "to chatter").
And according to https://www.etymonline.com/word/chatter === chatter (v.) early 13c., chateren "to twitter, make quick, shrill sounds" (of birds), "to gossip, talk idly or thoughtlessly" (of persons), earlier cheateren, chiteren, of echoic origin. Compare Dutch koeteren "jabber," Danish kvidre "twitter, chirp." Of teeth, "make a rattling noise from cold or fright," mid-15c. === Ordinary words can acquire a specialised technical meaning. For example === https://en.wikipedia.org/wiki/Machining_vibrations Machining vibrations, also called chatter, correspond to the relative movement between the workpiece and the cutting tool. The vibrations result in waves on the machined surface. This affects typical machining processes, such as turning, milling and drilling, and atypical machining processes, such as grinding. === Sometimes, machining vibrations make a ch-ch-ch-ch chattering sound. My opinions are that the correct technical phrase is 'machining vibrations', which is good for learned articles. But 'chatter' is better in the workshop. As in 'lubricate the drill bit to reduce chatter'. And here's another example === https://en.wikipedia.org/wiki/Chatter_(signals_intelligence) Chatter is a signals intelligence term, referring to the volume (quantity) of intercepted communications. Intelligence officials, not having better metrics, monitor the volume of communication, to or from suspected parties such as terrorists or spies, to determine whether there is cause for alarm. === Back to 'jargon'. === https://en.wikipedia.org/wiki/Jargon Accessibility issues With the rise of the self-advocacy movement within the disability movement, jargonised language has been much objected to by advocates and self-advocates. Jargon is largely present in every day language, in newspapers, government documents, and official forms. Several advocacy organisations work on influencing public agents to offer accessible information in different formats. [...] There is a balance to be struck, as excessive removal of technical terminology from a document leads to an equally undesirable outcome—dumbing down. === I think this last quote gets to the heart of the matter we're discussing. I suggest we learn better how to find a compromise (strike a balance) between precision and simplicity. -- Jonathan

tl;dr I don't think so, not very much. There are bigger fish to fry. I would appreciate comments on the last paragraph (before the footnotes), which can be read standalone. If opinion is at all favorable, I'll raise it with the PSF. Jonathan Fine writes:
I'm not a big fan of asking that everybody put such effort into documentation for code they're developing. IMHO, where available users should just buy books by professional writers written to their level, rather than imposing this burden on the software development project. Developers themselves should be asked to write concise, precise documentation. I don't think it's at all a good idea to burden them with "accessibility" issues. It's hard enough to write good notes for yourself a year hence! Tutorial writers, OK, they should be cautioned to avoid jargon, but if they aren't already judicious about using jargon, maybe they shouldn't be writing tutorials at all? What about documentation patches from users (including developers who didn't write the docs being edited)? In general, I favor restricting these to correcting bugs, missing information, and extremely convoluted syntax. If the docs use jargon (by which I mean "informal technical terms, often local to the project") which is intelligible to long-time users but may be off-putting to newcomers and infrequent users (of the documentation, not the software!), I think it is better to provide a glossary.[1] The problem with editing inline is that there are direct costs and a missed opportunity. The direct costs include the potential for introducing imprecision and outright documentation bugs, and code churn (increasing the cost of reading diffs). The missed opportunity is that a good glossary will also serve users who graduate to "informal write-only documentation" including archives of mailing lists and group chats, and the issue tracker. I'm not sure about the "conventional" accessibility issues (ie, excluding newcomers, non-native speakers, and translators). As a developer/maintainer I have had a small amount of contact with users with perceptual and motor disabilities, but have never heard them complain[2] about jargon. (Small sample, but before we presume they would benefit from simplified docs, we should consult experts.) Serving non-native-speakers is a tough call. On the one hand, they would be best served by good translations and glossaries of English jargon in their native language. You don't need to speak English at all to write good programs in programming languages based on English keywords, and the concepts are easier to understand, and precision easier to obtain, if you're not fighting with a second language. For many of my students, the first language is Chinese, the second Japanese, and the third English. English keywords and the occasional concept denoted by jargon don't faze them. The problem is more following simple directions about inserting punctuation, misspelled words, and so on -- the closest literal translations often are poor semantic matches, and so all English is awkward for them. But I can understand half (well, 10% ;-) of what their sempai are saying in Chinese, because of the keywords and borrowed jargon -- and so can the kohai. Jargon isn't a problem; it's just another symbol for an unfamiliar concept that they need to learn. On the other, we're not doing a good job of encouraging translators. There are a lot of volunteers in the translation community, and (like programmers) an important reward is getting their product into the distribution. (This is *not* a complaint about the Python maintainers. The costs of infrastructure and maintaining synchronization of translations with the original documentation are still quite high.) I suppose there must be corporations who are doing translations for their Python-based products, and we can do a better job of getting them to contribute them upstream (although we currently have the problem of "where is upstream?" since we don't distribute translations ourselves). Finally, before getting the project into the hairy maintenance issues that go with distributing translations, I suggest the PSF could buy the high-quality tutorial books and textbooks (and maybe dictionaries as well) for translators. Very cheap, but the symbolism that "somebody noticed, and they care!" is a big reward for many contributors. Another possibility would be complimentary tickets (and/or travel grants) to PyCon. From past experience I gather that many translators are more focused on their natural language than on the projects whose documentation they translate, so it's probably not worth sending them to big international PyCons to be lionized by the core developers and PSF board members. On the other hand going to a local PyCon might be attractive, especially if they got complimentary tickets to some of the parties, where they would be introduced to keynote speakers and the like, and would be lionized by the people they're writing for. Not to mention getting feedback. Steve Footnotes: [1] The convention in academic and textbook writing of providing definitions (and expansions of abbreviations and acronyms) at first use is a good one, but the glossary is essential in technical documentation because users frequently dip into the middle of a document for a specific entry rather than reading linearly. [2] In fact, users with disabilities rarely complain in my experience. They just point out their issues without attitude.

Hi Stephen Thank you for your message. I'll respond just to a few of your comments. HOW MUCH EFFORT ON DOCS ========================== Myself and you wrote:
Sections 6 and 7 (out of 31) in devguide for the Python project are on this. === https://devguide.python.org/docquality/ https://devguide.python.org/documenting/ === This is about 6.5%, of the devguide, by section count. There are at present 108 open documentation issues (out of about 6,000). This is about 2%. I'm proposing for example that we review, and if possible improve, these two sections in the devguide. This review would be evidence based. Not everyone need be involved in this. I suggest that doing this now would, over 3 years, significantly improve our Python documentation. AN EXAMPLE - super() ================== By chance, I wanted today to read about and then use super(). I found === https://docs.python.org/3/library/functions.html#super For practical suggestions on how to design cooperative classes using super(), see guide to using super(). === To my surprise, I found that this links, not to another part of the docs, but to === https://rhettinger.wordpress.com/2011/05/26/super-considered-super/ === This excellent blog post is not, of course, indexed for the docs search. THE GLOSSARY ============= You wrote:
Five days ago, I raised an issue (one of the 108 open issues), to improve search in the glossary. And thanks to Ammar Askar, there's already a patch and pull request. This delights me. https://bugs.python.org/issue34398 https://github.com/python/cpython/pull/8773 TRANSLATION ============ You wrote:
There's already prior art on this. See: PEP 545 -- Python Documentation Translations https://www.python.org/dev/peps/pep-0545/ One of the alternatives in PEP 545 is === Simplified English It would be possible to introduce a "simplified English" version like wikipedia did, as discussed on python-dev, targeting English learners and children. === I think this would be a good idea, particularly for the tutorial (and other beginner materials, such as the glossary). -- with best regards Jonathan

Hi Stephen I've just been reading the (excellent) discussion, started by Victor Stinner [Python-Dev] Translated Python documentation https://mail.python.org/pipermail/python-dev/2017-February/147416.html # Start of thread. You wrote, and asked for comments on:
I very much more prefer Victor's suggestion (I give the whole message): === https://mail.python.org/pipermail/python-dev/2017-February/147485.html IHMO translating the *whole* Python documentation at once by a professional translator can be very expensive, no somthing that the PSF would affort. Which language would you pick? Depending on what? We already have motivated translators for free who only ask us for the permission to make tiny changes to make their life simpler and make the doc more visible. I'm in favor of allowing them to translate and make the translated doc official ;-) IMHO a better usage of the PSF funding would be to organize some local sprints to translate the Python documentation. Such sprints are fun, cheap, and can be a nice opportunity to recruit free and motivated translators. We are looking for people involved to translate the doc the doc is updated, not only translate the doc once and go away. Right? === -- Jonathan

Jonathan Fine writes:
I think we can do both. My suggestion is very cheap, and requires no change to release management, or even action by release managers and committers: the PSF board could announce the policy tomorrow and start cutting checks next Monday, and python-dev wouldn't notice. (I'm not suggesting overnight rollout is a good idea, and practically speaking the board can't act that fast, of course. The point is that there's potential encouragement for translators, improved documentation for users, at zero cost to the code developers and release managers.) The suggestion of providing official translations in the distribution has been made before, and resisted by the maintainers and committers. I don't oppose the idea myself, I simply observe that resistance and the explanations offered, and assume there is good reason for it. Steve

o/
IMHO a better usage of the PSF funding would be to organize some local sprints to translate the Python documentation.
That's what we're already doing here in France for the french translation, and the PSF is already fouding them (thanks!) in Paris [1] and the AFPy [2] is founding them in Lyon. [1]: https://www.meetup.com/fr-FR/Python-AFPY-Paris [2]: https://www.afpy.org/ -- Julien Palard https://mdk.fr

On 18/08/18 01:59, Abe Dillon wrote:
While I don't entirely disagree with you, if I had been responsible for inventing that bit of Python I would probably have gone with "lambda" too. It had been part of my vocabulary as a computer scientist long before I met it in a programming language. Whether it's a *good* choice or not... possibly reusing "def" would fit people's expectations better, or perhaps it would have caused more confusion. Who can tell? Jargon becomes jargon because it's useful to enough people, for occasionally rather odd definitions of "useful". In the case of lambda, it's shorter than "inline function definition" and lambda calculus at least shows up on most CompSci courses. Once it settles into a group, you use it because other members of the group will understand what you mean and might not understand if you rephrase it.
One of the things Apple have always been very good at is thinking hard about user interfaces. What made the iPhone so good was that they emulated the right physical interfaces, so flipping a page when you're reading rather than pressing a button. -- Rhodri James *-* Kynesim Ltd

Responding out of order. [Rhodri James]
Yes, that's exactly what I was trying to say. An important point that I think keeps getting lost in this conversation is that Python's grammar, syntax, and standard lib are it's user interface. There are very different constraints on Python's UI than there are when humans have to communicate directly with other humans. I have no problem using words like "closure" or "lambda expression" or "ternary expression" when communicating with other humans about programming language features, but jargon doesn't often make sense as part of Python's UI itself. Again, we don't use the word "ternary" in Python's ternary expressions. [Rhodri James]
Yes, again: I understand the utility of jargon. I don't think "anonymous function" would be an improvement over "lambda" because, while it is fairly descriptive, it sacrifices too much brevity. However; the word "anonymous" is redundant. You can tell the function is anonymous by virtue of the fact that it doesn't have a name. "function" is only two characters longer than "lambda" and is actually descriptive, but it probably would have caused backwards compatibility issues (same with "func" or "fun"). "def" would have been even shorter than "lambda". [Rhodri James]
and lambda calculus at least shows up on most CompSci courses.
I suppose if by "courses" you mean "course plans", I highly doubt that the majority of CS classes cover lambda calc, though; I couldn't say for sure because I, like many programmers, didn't take CS in college. There are many disciplines that get by on basic algorithms, data-structures, and a pinch of theory. [Rhodri James]
If the group you're referring to are Computer Scientists, then I don't see why they would be confused by a syntax that omits the word "lambda" since very few languages use the word "lambda" to denote a lambda expression. [Rhodri James]
I don't see how "def" could cause more confusion than "lambda". Those who don't know what "lambda" refers to would at least have some notion of what "def" means, and those who have studied and know what lambda calculus is should also have very little trouble. I don't expect it would confuse someone well versed in computer science any more than a check-engine light would throw off an expert mechanic. They can at least google "python anonymous function" or "python lambda expression" and get results that tell you how to write a lambda expression in Python.

Rhodri James writes:
I was an economist then, and I'm an economist still, but I met lambda in 1977. Surely lambda has had that role in computer languages since shortly before I was born. I would guess anybody above a certain age would reach for "lambda" first for a keyword to denote or define an anonymous function. Not because of the lambda calculus, but because of Lisp. (OK, that's indirectly because of the lambda calculus.) Had Guido decided to change it to "def", I suspect he'd be regretting it slightly today, for reasons similar to the regrets about "range": we normally only allow omitting positional arguments at the end of the list. Maybe there's a better word than "regret". After all, It's hard to see how you could prototype range better than "range([START,] END, [STRIDE])", and the same might be true for "def [NAME] ([ARG0,] ...):".

On Tue, Aug 21, 2018 at 02:07:33PM +0900, Stephen J. Turnbull wrote:
Its pretty much a term of art. (Aside: "term of art" is itself a term of art: https://legal-dictionary.thefreedictionary.com/Term+of+Art ) I think that complaining about lambda is like complaining about "3-sigma versus 6-sigma processes" in process management. (Not computer processes, manufacturing processes and quality control.) Or for that matter, "mean" and "standard deviation" in statistics. The main difference is that most people are introduced to mean and stdev in secondary school, while functional programming idioms and lambda are generally stumbled across in the field. (I know that's how I learned of the term: through Python.)
Secure in the knowledge that Guido probably isn't reading this and won't contradict me *wink* I'm going to try channelling him. I think he would regret "def expressions", but not because of the range reason. I think its because he likes the relatively strict demarcation between statements and expressions. We have 4 statements that have a expression form: if...else versus ternary if expressions; for loops versus comprehensions; (soon) = assignment versus := assignment expressions; and def versus lambda. (Did I miss any? I don't include technicalities like dot attribute access versus getattr and similar.) It's notable that in none of those cases the syntax is quite the same in the two forms. There's always enough differentiation between the statement and expression that there's never any ambiguity which is intended. We don't have: result = if condition expression else expression where it is the lack of colons which hints that it is an expression, we have a completely different syntax. So I think Guido probably wouldn't like the idea of using def in expressions: def function(arg, callback=def: None): pass That's my guess, for what it's worth. -- Steve

[Stephen Turnbull]
According to Wikipedia <https://en.wikipedia.org/wiki/Anonymous_function> Lisp was the first language to use anonymous functions (introduced in 1958). [Stephen Turnbull]
Wikipedia lists the anonymous function syntax of 40+ languages <https://en.wikipedia.org/wiki/Anonymous_function#Examples> and only 5 (Lisp, Scheme, Python, Ruby, and Maxima) use the "lambda" keyword. Haskel uses a "\" which I'm pretty sure is supposed to look like the lambda symbol, but even that syntax seems unpopular too. [Stephen Turnbull]
I wasn't aware that Guido considered "range" to be warty. I like the way it mimics slicing syntax. It makes it easy for me to remember. It seems like a very pragmatic design. [Steven D'Aprano]
Secure in the knowledge that Guido probably isn't reading this and won't contradict me *wink* I'm going to try channelling him.
SUMMON THE GREAT CREATOR! I wonder if I say his name three times... Guido Van Rossum! Guido Van Rossum! Guido Van Rossum! [Steven D'Aprano]
I think he would regret "def expressions", but not because of the range reason.
I think its because he likes the relatively strict demarcation between statements
(I don't know why Gmail's quotes screw up formatting...) I don't think that's the reason those expressions have different formats than their statement counterparts. Expressions allow for more flexible arrangement than expressions because the order of execution of an expression doesn't have to follow the order of declaration. While it's more natural to say "do something to each item in this collection that meets some condition" you can't access variables before they're declared in statements so you have to tell the computer explicitly that you're looping over some iterable first. Expressions allow you to be more expressive. You don't have to put your edge-case checking up-front and in the way. When 99.9% of the time you just want: x = y you can shove the edge-case checking to the side and let the core logic shine: x = y if not edge_case else special_value # extra spaces added for emphasis besides: result = if condition expression else expression is super awkward to read out loud. That's not how I think at least. I've never hears someone say, "My child's name will be if it's a girl Sally otherwise Billy." All of the expressions use either the same or similar keywords or symbols *except* def and lambda. func = def <args>: <expression> Is about as different from the statement form as "x := y" is from "x = y". No name, no parentheses for the arguments. Finally, I know you've heard the other half of my anti-lambda manifest, but I don't know if Stephen Turnbull has, so I'll briefly present it again. It's not just the name "lambda" that bothers me, it's the arrangement of the logic and signature. I believe that the expressiveness that allows comprehensions to put the core logic in front of the less important (for readability) loop and filtering constructs, anonymous functions could have been arranged to put the logic in front of the (almost always) less important signature. The reason I say the signature is almost always less important is because one almost always uses an anonymous functions as an argument (key-function, callback, map, reduce, filter, etc.) to something that already defines the call signature it expects. Consider the alternate form: <expression> with <args> (thought there are many alternative possibilities) hand = sorted(cards, key=lambda card: value[card.suit] if card is not wild else max_value) hand = sorted(cards, by=value[card.suit] if card is not wild else max_value with card) # notice how unsurprising it is that the signature is "card" Oh wait... Did I accidentally replace "key" with "by"? Huh... It seems to make more sense even though the jargon is a "key function"... Oops! ;) Note: if this were a full proposal, lambdas with complex arguments or in certain situations would require parens: (<expression> with <args>) On Tue, Aug 21, 2018 at 9:31 AM, Steven D'Aprano <steve@pearwood.info> wrote:

On Wed, Aug 22, 2018 at 3:56 AM, Abe Dillon <abedillon@gmail.com> wrote:
I've never hears someone say, "My child's name will be if it's a girl Sally otherwise Billy."
"My child's name depends on gender - if it's a girl, Sally, otherwise Billy." Seems fine to me. You can always come up with something awkward in a particular order, but it's not the order that made it awkward.
Okay, let's read that. hand = # we're assigning this to the name 'hand' sorted( # calling the function named 'sorted' cards, # positional argument, whatever's in the 'cards' variable by= # keyword argument, what comes next is the 'by' argument value[card.suit] # subscript 'value' with 'card.suit' if card is not wild # yep else max_value # so we have an alternative with card # WAIT WAIT WAIT Once you get to 'with card', you have to go back and completely reinterpret everything prior to that as a function. You have to scan back and go "hang on, so exactly how much of this is getting wrapped up into a function here?". Contrast the Python version: hand = sorted(cards, key=lambda card: value[card.suit] if card is not wild else max_value) hand = # we're assigning this to the name 'hand' sorted( # calling the function named 'sorted' cards, # positional argument, whatever's in the 'cards' variable key= # keyword argument, what comes next is the 'key' argument lambda card: # a function taking one argument value[card.suit] # subscript 'value' with 'card.suit' if card is not wild # yep else max_value # so we have an alternative ) # and we're done The only part where you have to back up and change your interpretation is when you hit "if card is not wild", which reads well enough to justify the odd ordering. (JFTR, I wouldn't implement a deck of cards this way. It implies that there is exactly one wild card, where many decks of cards have at least two. In English, "card is not wild" can be interpreted as a membership check, but in Python, it is only an identity check; you're capitalizing on false readability by using this notation.)
Oh wait... Did I accidentally replace "key" with "by"? Huh... It seems to make more sense even though the jargon is a "key function"... Oops! ;)
I'm sure it would make even more sense if you wrote it this way: hand = sorted(cards, by="suit") That's how SQL works - you just name the column that you want to order the results by. But if you think "by" is a better keyword here, start explaining why your ordering is done with an anonymous function, not with an attribute name. ChrisA

[Chris Angelico]
The revelation that it's a function should come when you read the "by" or "key". If you don't know what that parameter is, then that's where the "wait wait wiat!" should happen. Then type "help(sorted)" in a console or something. Another hint can come from the appearance of an undeclared variable: card. (I know, I know: I didn't declare several variables, just imagine that 'card' is the only variable not previously declared). It's no more surprising than reading a comprehension: initials = {person.name[0] for person in people if person.name} initials = # we're assigning this to the name "initials" initials = { # it's a dictionary or set of something initials = { person.name[0] # I'v never seen "person" before, this must be a comprehension or something # anyway, no ":" means it's a set of the first letter of each person's name intiials = { person.name[0] for person # WAIT WAIT WIAT WHAT?!? Just kidding, I saw this coming... [Chris Angelico]
If the logic is simple enough, you can just use a reference to the method from the class: hand = sorted(cards, by=Card.suit) # where Card is the class That's why I tend to use a more complex example. Otherwise the lambda isn't really justified. [Chris Angelico]
JFTR, I wouldn't implement a deck of cards this way.
I don't implement decks of cards often, but in toy problems; I find just using 2-character strings works fine: Ace_of_spades = "As" Ten_of_hearts = "Th" etc... That can easily be extended by a named tuple initialized with unpacking: Card = namedtuple("Card", "rank suit") Ace_of_spades = Card(*"As") [Chris Angelico]
It implies that there is exactly one wild card, where many decks of cards have at least two.
I don't know of many games that have wild cards, but that's a simple remedy: hand = sorted(cards, by=value[card.suit] if card not in wilds else max_value with card) [Chris Angelico]
I promise that wasn't my intent. Since both my proposed form and the lambda form use the same expression, it doesn't really tip the balance in favor of my argument. Also, most toy card problems I work with use a finite, immutable set of cards, so identity checking isn't *that* weird. On Tue, Aug 21, 2018 at 1:12 PM, Chris Angelico <rosuav@gmail.com> wrote:

On Wed, Aug 22, 2018 at 4:56 AM, Abe Dillon <abedillon@gmail.com> wrote:
That right there is unacceptable. You should not have to know the destination to understand what something fundamentally is. You can't redefine language syntax based on the function being called. ChrisA

[Chris Angelico]
That right there is unacceptable. You should not have to know the destination to understand what something fundamentally is.
You don't *have* to know what the parameter "key" is to know that (value[card.suit] ... with card) is a function. You can identify that it's a function just by reading the full expression. However, if you don't know what "key" is, then it'll cause far more confusion than the late declaration of the function's parameters. [Chris Angelico]
You can't redefine language syntax based on the function being called.
That's not at all what I suggested. You were walking through my example from the reader's perspective. I was explaining how the reader will often have plenty of context about what they're reading before they get to the signature declaration. Whether it be because they know what the "key" parameter means or because they know "card" is undeclared or both. I never claimed the language syntax should be based on the function being called. func = value[card.suit] if card not in wilds else wild_value with card Works independent of the function being called. It's just not a common use case because it obviates the expressiveness of anonymous functions. You might as well use a "def" statement. The thing that makes callbacks difficult is not knowing how they're called. I tried to throw a little JavaScript into my curriculum once thinking "how bad can it be?" and suggested my students work on a project using the Force Directed Graph from D3.js <https://bl.ocks.org/mbostock/1062288>. That was a HUGE mistake not because anonymous functions are confusing but because the example (at the time) had no documentation at all (like this one <https://bl.ocks.org/mbostock/4062045>) and used mysterious callbacks everywhere. The main documentation for D3.js is super difficult to navigate, when all you want to do is slightly modify one of the examples (use svg images for the nodes and have stats display "on mouse over"). If you don't know what "".join() does, then you're going to have trouble making sense of: def initials(person): return "".join(name[0] + "." for name in person.names if name) The late assignment of the name variable will NOT be your main source of confusion. If you do know what "".join() does, then it should take you much less context to realize you're reading a generator expression. By the time you read the yet-to-be-assigned "name" variable you should be tipped off. On Tue, Aug 21, 2018 at 1:58 PM, Chris Angelico <rosuav@gmail.com> wrote:

On Wed, Aug 22, 2018 at 6:24 AM, Abe Dillon <abedillon@gmail.com> wrote:
Python's parser is *deliberately* incapable of backtracking this far in its definition of syntax. So if you want to have something where the first long slab of it is entirely acceptable as an expression, right up until you get to the "with" at the end, it's not going to work. You then said that it was the parameter "key" that told you that this would be a function, which is also unacceptable in Python syntax. So how do you intend to do this? And you still haven't done anything to show that this is actually better than "lambda card:" at the beginning. I'm done. ChrisA

[Chris Angelico]
Python's parser is *deliberately* incapable of backtracking this far in its definition of syntax.
Can you explain how far the parser is capable of backtracking? It seems like <expression> with <signature> would require a similar amount of backtracking to ternary expressions: <expression> if <condition> else <expression> If the preceding expression is the same in both cases, then the parser needs to backtrack just as far when it finds an "if" as when it finds a "with". [Chris Angelico]
You then said that it was the parameter "key" that told you that this would be a function, which is also unacceptable in Python syntax.
That was *never* a statement about syntax. It was about the context clues a reader has, not the parser. The proposed syntax: <expression> with <signature> is an expression that evaluates to a function object regardless of any parameter or any function it might or might not be passed to. My argument is simply: Most cases where an anonymous function is more expressive than a named function are also cases where, *from the perspective of a human reading the code*, the signature is noisy preamble that gets in the way of the expression. In psuedo code, people tend to write things like:
hand = sorted(cards, by=card.suit)
Obviously that wouldn't compile because the computer doesn't know what "card" is. However;
hand = sorted(cards, by=lambda card: card.suit)
puts a bunch of noise that's mostly of interest to the computer in front of the expression that's of interest to the reader. There is precedent for late-variable-binding in Python expressions already (e.g. comprehensions), so it makes sense to me that the expression version of function declaration could also bind the signature after the main expression. The same logic follows for mappers, reducers, filters, callbacks, event-handlers, etc. [Chris Angelico]
So how do you intend to do this?
I don't intend any of this to make its way into Python. It's a case study of expression design. It's interesting to me to explore such alternatives. It's fine to prod it and examine its flaws as Jonathan Fine has. [Chris Angelico]
And you still haven't done anything to show that this is actually better than "lambda card:"
I'm trying to, but I also have to answer all your misconceptions about the idea (like that the syntax is function or parameter-dependent). [Chris Angelico]
I'm done.
OK. I'm sorry if I upset you.

On Wed, Aug 22, 2018 at 8:45 AM, Abe Dillon <abedillon@gmail.com> wrote:
I have to defer to someone who knows in more detail here, but the parser will look ahead one "token", whatever a token is. (Technically it doesn't backtrack, it looks ahead - same difference.) In order for the ternary-if to work, the expression before the if has to be of a more restricted type than just "any expression" (for instance, you can't put a lambda function there, unless you parenthesize it). But I'm not fluent in all the details, and I definitely am not comfortable citing exactly what the limits are. The last time I tried editing the grammar, weird things happened. ChrisA

[Chris Angelico]
Interesting. I really need to try delving into the nuts and bolts of Python. I didn't know that about ternary expressions. I don't know if you saw my recent discussion with Jonathan Fine, but he brought up some good points too.

Chris Angelico writes:
Tokens are basically keywords, identifiers, most single punctuation characters, and indentation. Some strings of punctuation are tokens by special dispensation.
It's not that it's a restricted expression, it's that a valid lambda will consist of a syntactically complete expression. If you then place "if" after that lambda without parenthesizing, the parser will think that the lambda contains the whole ternary expression because pretty much any Python expression has a value that can be implicitly cast to bool. Steve

Thanks, Stephen. That's interesting. So the parser can see one token past, for instance; what would be the end of an expression, see "if", and know to expand the AST?

Abe Dillon writes:
Yes, if you want to think about it that way. I think about it in terms of the parser receiving tokens one at a time, using to revise the AST, until it can't. Like a five-year-old building a fort by piling up pillows. She's done when she's out of pillows, or the whole thing falls over due to imbalance. She doesn't have a grand plan, she just puts pillows wherever they fit. At the point where no work can be done, the parser either has a token in hand, which is a syntax error, or it's at end of input. In the latter case, it either has a complete syntactically correct AST, or it's a syntax error. In the end it works the same as your description, but I don't think of it in terms of the parser knowing "where" it is in the program, but rather in terms of whether it can do more work on the AST with the token (or EOF) in hand. Only when it runs out of input does it "look at" what it's built so far to check if it's done. If you think of expressions having their own subparser, the model is a little more subtle. I think of the subparsers as being coroutines receiving tokens via (yield) from their parent. This implies that when the subparser actually returns an AST, the parent already has the token that the subparser balked at. In some sense, there's no lookahead in the sense of something you save away to fully process later, or pass to another actor to process. You're always operating on a current token. Steve

Stephen J. Turnbull wrote:
For understanding what kinds of things an LL parser can parse, it helps to have gone through the exercise of implementing a recursive descent parser. The classic way to do that is to write a function for each production in the grammar. E.g. if you have a production expr ::= term ['+' expr] then you would write a function structured like this: def parse_expr(): parse_term() if current_token == '+': next_token() parse_expr() What other stuff you do in it depends on what you want the parser to accomplish. If you want it to build a parse tree, you could do something like this: def parse_expr(): result = parse_term() if current_token == '+': next_token() operand2 = parse_expr() result = BinopNode(result, operand2) return result
Not so much where it is in the program, but where it is in the *grammar*. For example, if parse_term() gets called, it knows it must be looking at the beginning of a term. If the current token is not one of the ones that can begin a term, then there is a syntax error. The fact that a recursive descent parser always knows where it is in the grammar is useful, because it can be used to produce helpful error messages. For example, if it gets stuck in parse_term() it can say something like "I was expecting a term here, but this token doesn't look like the beginning of a term." Unfortunately, Python's parser doesn't seem to make much use of this. :-(
If you think of expressions having their own subparser, the model is a little more subtle. I think of the subparsers as being coroutines
That's kind of the way an LR parser works. An LR parser is more powerful than an LL parser, because it can effectively explore several possible parsings in parallel until one of them succeeds. But I don't think Python uses an LR parser, because its grammar is required to be LL(1). If you're interested in this stuff, I recommend either taking a computer science course or reading a good book about the theory of parsing. It will bring a lot of these concepts into sharp focus. -- Greg

Greg Ewing writes:
I deliberately decided not to go this route. I'm curious whether Abe found both posts useful. (Comparisons are invidious; please don't. ;-)
[Concise useful description of what this means and why it's useful elided.]
Unfortunately, Python's parser doesn't seem to make much use of this. :-(
Indeed, and that's part of why I chose the route I did. But the main point is that in the context of the particular example (the lambda swallowing the if-else expression if the lambda is not parenthesized), the "keep going until you can't" aspect of subpattern matching (used for ambiguity resolution) is the cause of the need for parentheses here.

On Tue, Aug 21, 2018 at 05:45:53PM -0500, Abe Dillon wrote:
Can you explain how far the parser is capable of backtracking?
Its an LL(1) parser, if I recall correctly, so if you look at the details of LL(1) parsing, that should answer the question. https://en.wikipedia.org/wiki/LL_parser But if I'm reading the Wikipedia page correctly, I think the answer is "no backtracking at all".
I don't think needs any backtracking. The parser doesn't have to read the "if" and then go back to re-read the previous expression. It can look ahead from the expression by one token, see the "if", and recognise it is a ternary if. -- Steve

Hi Abe First, I have reservations about the name lambda. But there's a lot of code out there that uses lambda, and I'd like that code to continue to run. You wrote:
func = value[card.suit] if card not in wilds else wild_value with card
I thought I'd try this, and variants, in the Python interpreter. I got # An expression. It's valid syntax, get run-time error.
value[card.suit] if card not in wilds else wild_value NameError: name 'card' is not defined
# An expression. It's valid syntax. Its value is a function. No run-time error.
lambda card: value[card.suit] if card not in wilds else wild_value <function <lambda> at 0x7ff815e2bbf8>
# If Python were enhanced, an valid expression whose value is a function.
value[card.suit] if card not in wilds else wild_value with card SyntaxError: invalid syntax
My understanding is that you prefer
How do you feel about this, as a means of defining an anonymous function?
with IDEN: EXPRESSION
We can't adopt it, of course, because it's already valid syntax, but with semantics.
Now for a trick question. Consider
fn = (lambda : EXPRESSION) This produces a function that has zero parameters.
How would you write this, using 'with'. Would it be:
fn = (EXPRESSION with) I think this looks rather odd.
-- Jonathan

[Jonathan Fine]
Yes. I'm under no delusion that lambda will be replaced any time soon. Nor do I believe any alternative I suggest will be enough of an improvement to warrant breaking the "there should be one and only one obvious way to do something rule". So I don't expect this conversation to lead to any change to the language, I just think my case that it's sub-optimal might inform future design decisions. Though it doesn't look like anyone finds it especially convincing. [Jonathan Fine]
Correct. My argument is two fold: 1) the name "lambda" is needlessly esoteric. 2) the format of lambdas is "backwards" I tried to focus on the name gripe in this thread because trying to explain both at the same time caused confusion. However, Stephen Turnbull's and (more so) Steven D'Aprano's comments made the format argument semi-relevant and I can't help getting on that soap-box... [Jonathan Fine]
How do you feel about this, as a means of defining an anonymous function?
with IDEN: EXPRESSION
I think it's better than lambda. I can't decide if I like it more than:
def IDEN: EXPRESSION
Because def is more clearly connected to function declaration and i'm somewhat sympathetic to the idea of expressionizing "with"-statements. The only reason I don't prefer:
EXPRESSION def IDEN
to
EXPRESSION with IDEN
Is that it looks weird to me. It just doesn't seem right. [Jonathan Fine]
That's a good point. I hadn't considered that. There are several possible formats that put the expression before the signature definition. The specific form isn't quite as interesting to me. I would even prefer something like:
def (EXPRESSION [<seperator> SIG])
Mostly because "def" could then have a double meaning: "define" and "deferred expression". I think that's kinda neat. My problem with putting the signature first is that it usually amounts to noisy preamble that gets in the way of the important code. In pseudo code you'd often write:
hand = sorted(cards, by=card.suit)
But obviously the compiler doesn't know what "card" is since it's never declared, so we write:
hand = sorted(cards, by=lambda card: card.suit)
Notice that the information that's important to the reader: the expression, is pushed behind information the computer needs but the reader probably doesn't care about. My claim is that in most cases, the signature is more noise than signal, so it should come after the expression. A function passed as a callback, key-function, mapper, reducer, filter, event handler, etc. has a mostly pre-defined call signature. In most other cases, you're better off using a named function. Thanks for your input! On Tue, Aug 21, 2018 at 3:51 PM, Jonathan Fine <jfine2358@gmail.com> wrote:

On Wed, Aug 22, 2018 at 4:56 AM, Abe Dillon <abedillon@gmail.com> wrote:
Fair enough. To be fair, I use decks of cards primarily for non-game usage (for instance, teaching data structures and algorithms - cards laid out on a table can represent a tree, heap, array, etc), and my decks of cards are artistic. A deck containing four suits of thirteen cards plus one joker would have 53 cards, which is a prime number; printing 54 cards lets you lay them out as 9 by 6 on a sheet, so it's easy to add a second joker. Some decks (I have an Alice in Wonderland themed deck) have *four* jokers. As such, the most logical way to do this would be as an attribute of the card. Its jokerness is as much a feature as the clubness of another card. You can pick up a physical card, look at it, and say "This is a joker"; you don't have to see if it's in a list of specific known jokers. hand = sorted(cards, by=value[card.suit] if not card.wild else max_value with card) Honestly, though, it'd usually be more interesting to sort by rank within suit. What you're doing here would group the cards by suit, ignoring their ranks; more useful would be: hand = sorted(cards, key=lambda card: (card.is_wild, card.suit, card.rank)) Much cleaner. No conditionals needed. ChrisA

[Chris Angelico]
I do too. They're a great tool for visualizing and physically trying out different techniques. [Chris Angelico]
In most cases I've seen wild cards used, it's a declaration about a certain card (e.g. "Eights are wild." or "The 2 of clubs is wild."). I've found that if you're trying to model a game like poker or Monopoly, it's tempting to add complexity to simple objects, but it can lead to problems later on. A card doesn't know if it's wild. That's a function of the game being played. An ace may be high or low. On Tue, Aug 21, 2018 at 2:06 PM, Chris Angelico <rosuav@gmail.com> wrote:

On Wed, Aug 22, 2018 at 6:33 AM, Abe Dillon <abedillon@gmail.com> wrote:
Well, okay. Then you should check if the card is a joker, rather than checking if it's wild. That means your sort function is "by suit, and within that by rank, but jokers are at the end" (ignoring wildness). That said, though... I've seen and used a Canasta deck of cards, which have game-specific information printed on them. Physical cards. So there's precedent for that! ChrisA

On Tue, Aug 21, 2018 at 01:56:16PM -0500, Abe Dillon wrote:
The revelation that it's a function should come when you read the "by" or "key".
I disagree. The most important fact is that it is a function, not specifically what it does. Consider: widget.register(value[a](x) with x) (As per your earlier example of ternary if operator, I've inserted spaces to emphasis the gap.) At first it looks like you are evaluating value[1](x) eagerly, right there in the method call, and then you have to backtrack and change your expectation about what you just read when you get to the end and see the declarations. Even Forth, which (apart from its use of extremely concise commands) is most (in)famous for backwards things writing in Reverse Polish Notation, or programming by Yoda *wink* nevertheless puts the "function declaration" before the body. Classically, you define a function like this: : func DUP DROP ; The colon tells the interpreter to start compiling a function named "func", DUP and DROP are the commands in the body of the function (in this case, a pointless combination), and the semi-colon says to stop compiling and bind the new function body to the given name. Classical Forth doesn't have named function parameters, but some RPN languages do, and likewise they come first. In the HP calculator RPN language, we write something like: << -> x << DUP DROP >> >> to grap an argument and assign it to "x". Given some sort of look-ahead, it's *possible* to put the parameter list at the end of the function body: def function: do_this(a) do_that(b) do_something_else(c) with (a, b, c=None) but I think you can see why that would be annoying. You don't even know which names are global and which are parameters until you get to the very end of the function. Blah. The same applies to function expressions. Given the function body: value[a](x) which of value, a and x are global names and which are parameters?
If you don't know what that parameter is, then that's where the "wait wait wiat!" should happen.
"Wait wait wait!" should ideally never happen. In programming, surprises are not a good thing, and they're even less good when they are retroactive. "Ha, fooled you! You thought you were dealing with an eagerly evaluated expression, but it was a deferred function body declaration instead! Mwahahahaha!!!" -- Steve

On 22/08/18 07:11, Steven D'Aprano wrote:
This, by the way, is why think using the same syntax for function definition and generator definition was a mistake. It's only when I reach a "yield" statement that I realise my expectations for this code are wrong. (That was a decision made a long time ago, and I'm not fool enough to think that there's any benefit in trying to change it now. I can still be a grumpy old man over it, though.) -- Rhodri James *-* Kynesim Ltd

Hi Rhodri You wrote:
This, by the way, is why think using the same syntax for function definition and generator definition was a mistake. It's only when I reach a "yield" statement that I realise my expectations for this code are wrong.
Here's something that might help, and surprise, you. This has been present since Python 2.5.
I think what's happening is this. Even though the None-guarded yield has been optimised away, it leaves a residue. Namely, that there's a yield in the function. Hence fn() is an iterator. Having explained the surprise, here's how it can help you. Suppose you have a long function body, with a single yield at the bottom. If you write like this: def my_very_long_function_with_one_yield_point(...): if None: yield # This is a generator function. then the next programmer can know immediately that it's a generator function. -- Jonathan

On 22/08/18 14:38, Jonathan Fine wrote:
If by "help" you mean "make even more confused", then yes. Surprise is a given with generators, as I said.
Ew. I'd prefer this way of doing it: def my_very_long_function_with_one_yield_point(...): # This is a generator -- Rhodri James *-* Kynesim Ltd

On Thu, Aug 23, 2018 at 3:56 AM, Rhodri James <rhodri@kynesim.co.uk> wrote:
Actually, it fails unless fn returns some sort of iterable.
Or you could use a return type annotation. Why should generator objects be special? A generator function is very similar to a function that returns a list, except that it can yield values as it gets them, rather than batching them up to the end. A generator function is a function which returns an iterable object of the type "generator". How is it different from a function that returns an integer? They return different things. How do you show what a function returns? You annotate it, put it in the docstring, put it in external docs... It's a function. It does something, it returns something. That's it. ChrisA

Fwiw, I usually don't do def foo(): if False: yield None But simply: def foo(): return () That the returned iterable is not a generator seldom matters. Stephan Op wo 22 aug. 2018 21:17 schreef Chris Angelico <rosuav@gmail.com>:

Rhodri James wrote:
This, by the way, is why think using the same syntax for function definition and generator definition was a mistake.
I think I remember arguing the same thing back when generators were being devised. But there are arguments the other way too. From the outside, a generator is just a function that returns an iterator -- the fact that it works by yielding is an implementation detail. When you write an ordinary function that returns an iterator, the fact that it returns an iterator needs to be conveyed some other way, such as by its name or documentation. if you can do that for an ordinary function, you can do it for a generator just as well -- and probably should, so that you can tell what it returns without having to look at its definition. If the name of the function indicates that it returns an iterator, or there's a docstring at the top what says so, then you won't be surprised when you find a yield in it somewhere. -- Greg

On Thu, Aug 23, 2018 at 9:02 AM, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
def gen1(x): return iter(range(x)) def gen2(x): i = 0 while i < x: yield i i += 1 def gen3(x): if i % 2: return gen1(x) else: return gen2(x) Which of these three are generator functions? Technically only one of them is... but how would it make any difference? ChrisA

[Steven D'Aprano]
I was trying to say that the context almost always gives away that the reader should expect a function. Again, the pseudo code: hand = sorted(cards, by=card.suit) Is usually enough for most people to understand. When you add in what the computer needs to make the whole thing mechanically unambiguous: hand = sorted(cards, key=lambda card: card.suit) You can see the noise added compared to the pseudo code. The difference (to me) looks like this: hand = sorted(cards, by#=#############card.suit) Ideally, we could move that noise out of the way so that the intent is more clearly expressed: hand = sorted(cards, by=card.suit ########## Functions, variables and parameters are normally named such that they give away lots of context (or they should be). Context that's available to the reader but not the computer. [Steven D'Aprano]
Consider: widget.register(value[a](x) with x)
First, how is your example any worse that the delayed binding of generator expressions? widget.register(value[a](x) for x in things) Of course the context of what they're reading builds as they read it. You could put those spaces anywhere: widget.register(value[a] (x) for x in things) Delayed binding works because human readers can deal with a little ambiguity in what they're reading especially if it means putting the intent of the code before the book keeping. If we're assuming a naive reader who's never seen the widget.register method and method and variable names that are pretty ambiguous (not unheard of, especially in anonymous functions) then I would say the blocker is not knowing what widget.register is in the first place. If you don't know that, then what point is continuing to read? Will knowing the kinds of object being passed clear everything up? widget.combobulate(5, "elephant", True) Once the reader has encountered widget.register they'll know it takes a function as an input. Just like anyone who's used time.sleep will be thrown for a loop as soon as they see lambda in: time.sleep(lambda x: value[a](x)) [Steven D'Aprano]
Yes! Common ground! <doing my common ground dance> Named functions serve a different purpose than anonymous functions. They usually handle situations where the interface is more important than the implementation. def square_root(x): ... Better spit out the square root of whatever number I give it. I don't care how. Anonymous functions are almost always used in contexts where the interface is implied and the important bit is *what* it does: ui_element.on_mouseover(<what to do> with event) [Steven D'Aprano]
The same could be said of the value[a](x) in: widget.register(value[a](x) for x in things) [Steven D'Aprano]
It happens when someone has never seen the map function used or sorted used with a key function. It happens during the time where reading code is hard to begin with. The "wait wait wait" happens when you don't know what map is. Once you learn that, then you learn that the first parameter is a function. Then whenever you see map, you should expect the first parameter to be a function. No amount of broadcasting that the first parameter is indeed a function will cure the confusion of not knowing what map, or wiget.register is. *Having said all that:* Jonathan Fine pointed out that the <EXPRESSION> <SEPARATOR> <SIGNATURE> format that I've been championing (where I've been using "with" for the separator) has a subtle flaw where empty signatures are pretty awkward: d = defaultdict(100 with) It *kind-of* works with "def" and you read it as, "the preceding expression is deferred" followed by an *optional* signature declaration. d = defaultdict(100 def) But it's not great. Another alternative is to use some (ideally short) prefix and making the signature declaration optional: <PREFIX> <EXPRESSION> [<SEPARATOR> <SIGNATURE>] d = defaultdict(def 100) hand = sorted(cards, by=def card.suit with card) of course there are many possible choices for the prefix and separator and subtle alterations like: hand = sorted(cards, by==>card.suit with(card)) . # where '=>' is the prefix, it just blends nicely or: d = defaultdict(100 with()) Anyway, none of that interests me. What interests me is the recognition of *why* expressionization of statements often leads to a re-ordered version of the original. My thesis is that expressions are slightly more flexible than statements which allows for a more expressive ordering that is sometimes better for readability. I think it's important to understand that if we ever expressionize other statements like try-except, with, etc.

On Wed, Aug 22, 2018 at 12:11:40PM -0500, Abe Dillon wrote:
You are judging that from the perspective of someone whose native language makes it easy to say "sorted by foo" (for some value of foo). We shouldn't judge syntax proposals just on the cases that are carefully chosen to showcase them at their best. Especially not trivial cases. Here is a line from the importbench tool in Python 3.5: def bench(name, cleanup=lambda: None, *, seconds=1, repeat=3): Under your proposal, that becomes: def bench(name, cleanup=None with ???, *, seconds=1, repeat=3): except I'm not really sure what goes in the ??? for an empty parameter list. But whatever it is, do you still think it is obvious that people will recognise "None" to mean a function without having to backtrack? And from the threading tests: t = threading.Thread(target=lambda: None) difflib tests include this call: sm = difflib.SequenceMatcher(isjunk=lambda x: x == ' ', ...) which becomes: sm = difflib.SequenceMatcher(isjunk=x == ' ' with x, ...) The expression x==' ' doesn't look like a function to me.
Ideally, we could move that noise out of the way so that the intent is more clearly expressed:
So you say. I say it isn't noise, and if you ask me to express my intent, I'll state that it is a function first and at the beginning of the expression, not the end.
Who says its worse? I think they are equally as problematic. Many people have trouble with comprehension syntax precisely because it breaks left-to-right order. I think we ought to be cautious about emulating that elsewhere. -- Steve

On Thu, 23 Aug 2018 03:44:07 +1000, Steven D'Aprano wrote:
On Wed, Aug 22, 2018 at 12:11:40PM -0500, Abe Dillon wrote:
Hold that thought.
Okay, so I'm trying to follow along, and not jump in with another "me, too" response. Statements and expressions don't read from left to right. Blocks and functions don't read from top to bottom. Some people read programs from the inside out, assembling bigger and bigger building blocks until the entire program is just a building block. Others read programs from the outside in, decomposing really blg blocks until the remaining blocks are small enough to see and understand without further decomposing. Reading a program, let alone figuring out what it does, let alone figuring out what it's supposed to do, is not a simple single pass process. Something has to come first, and something has to come next, and something will end up coming at the end. Regardless, the reader will have to save some context, or go back and look at the beginning again. So is it better to see the definitions first, and the logic second? Or is it better to see the logic first and the definitions later? I don't know; it depends. It may even vary over time inside the same code base. When you talk about intent, I think about use cases. In the difflib code I quoted above, is the intent to define a function, or to instantiate a SequenceMatcher? Well, no, it's probably to compute some sort of difference. Instatiating a SequenceMatcher and defining isjunk are details. So you're both wrong. :-P Or you're both right. :-/ A large part of my previous job was digesting papers written by economists and mathematicians, and then translating the ideas and algowithms in those papers into code. Sometimes, I'd see stuff like this: Given x = the width of a widget and y = the price of that widget, let f(x, y) be x + y. And sometimes, even in the same paper, I'd see stuff like this: Let f(x, y) be x + y, where x = the width of a widget and y = the price of that widget. Which one is harder to read, or expresses the intent better? If that's what we're down to, then an assignment operator is a trivial exercise. Dan

On Wed, Aug 22, 2018 at 06:50:29PM +0000, Dan Sommers wrote:
In this case, "intent" could refer to (for example): Should we accuse Fred Bloggs of plagarism or not? +- decide whether two documents came from the same source; +- decide whether the diff between two text strings falls within some threshold; +- initiate and use a SequenceMatcher object; +- provide an isjunk predicate function; +- implement a specific predicate function. Because we are talking about lambda syntax specifically, I didn't think the higher hierachies of intent were relevant, so I didn't mention them. I thought we could focus on the two relevant to the syntax we're discussing: Provide an isjunk predicate function; +- implement a specific predicate function. and take the higher levels as given. Given those two levels, "Provide a predicate function" is at a higher level than the implementation of that predicate function. I'm sorry if that wasn't clear. -- Steve

On Thu, 23 Aug 2018 21:40:12 +1000, Steven D'Aprano wrote:
Yes, the discussion is/was about lambda syntax, and about how quickly I (or someone else) can recognize that isjunk is being defined as an anonymous function. Perhaps I missed that the larger context had already been established. To focus my argument within your clarification: if I have all of that context, then I don't have to parse the code to know that the isjunk parameter is a function. And if parsing the anonymous function gives you (the generic you) that much trouble, then please break it out into a def statement instead. Flat is better than nested. IIRC, you push for named functions in all but the most trivial cases anyway (and I tend to agree). Dan

Replying out of order: [Steven D'Aprano]
I know I tend to write long-winded responses, but please read them fully before replying. I covered this. [Steven D'Aprano]
But whatever it is, do you still think it is obvious that people will recognise "None" to mean a function without having to backtrack?
It's not clear what you mean by backtracking at this point. cleanup=None with() requires no more backtracking than any other compound expression. cleanup=children.oldest().room doesn't tell you what kind of object is being assigned to cleanup. Is it a function? Who knows? Even if you know what 'children' is and what the 'oldest' method returns, you still don't know what's being assigned to cleanup without reading the entire expression. There has never been a guarantee that expressions evaluate left to right simply by virtue of the fact that an order of operations exists. The LL(1) parser limits parsing complexity to expressions which require at most one token look-ahead. Usually (I'll come back to this) that isn't hard for humans who process text in chunks of multiple tokens at a time. [Steven D'Aprano]
And from the threading tests: t = threading.Thread(target=lambda: None)
t = threading.Thread(target=None with()) seems pretty straight-forward to me. [Steven D'Aprano]
sm = difflib.SequenceMatcher(isjunk=x == ' ' with x, ...) The expression x==' ' doesn't look like a function to me.
You don't think that perhaps that's because it's brand new syntax? x=='' doesn't look like a function because it's not a function. You could play the same game with literally any compound expression:
func = ", ".join
", " doesn't look like a function to me! [Steven D'Aprano]
Don't you think that depends on the situation at all? Don't you think there are cases where the fact that you're passing a function and the call signature of said function are exceedingly clear from context? ui_element.on_mousover(<do something> with event) We already have a way to declare a function signature first. If you think it's paramount, then just def it. If you honestly don't understand my position at all. If it's always a surprise to you that ", ".join() takes an iterable of strings or that sorted takes a key-function that takes element from the iterable being sorted, or that on_mousover takes a function that takes an event object etc. etc. etc. then I guess I've never met anyone quite like you. I don't know how to communicate my point of view any better than I already have. [Steven D'Aprano]
You are judging that from the perspective of someone whose native language makes it easy to say "sorted by foo" (for some value of foo).
This argument is such a tiring distraction. Please stop. If it's all just random symbols to some non-english speaker, then It doesn't matter either way to them. They can still deal with tokens in the same way as the LL(1) parser. Only one look-ahead. That's not at all how the world works, but I don't have the energy to get into that discussion right now. I've been writing a veritable novel on my views on lambda for over a week now and people keep re-tredding the same ground. [Steven D'Aprano]
We shouldn't judge syntax proposals just on the cases that are carefully chosen to showcase them at their best. Especially not trivial cases.
We can judge it by examining cases where it might be problematic, but there's no way to keep people from abusing coding constructs to produce unreadable code, so just throwing out random chunks of code like a.b[c:d]-e**f(g, h=i) + {j & k, l*(m-n(o,p))} with e, k then saying "looks bad to me" offers no insight into the pros and cons of the proposal. Well, yeah. It looks bad because it's terrible code. It feels like you're not even trying to understand the basic premise of my position. Otherwise, I would be delighted to move past the simplified examples and on to more complex and probably troublesome counter examples. Hell, we can talk about how this would effect blind space aliens who can only hear ultra-sonic chirps and are essentially incapable of learning English after we get past this roadblock...

On Wed, Aug 22, 2018 at 06:28:45PM -0500, Abe Dillon wrote: [Steve -- that's me]
Yes, I accept that's not clear. Sorry. What I mean is that moment of having to reinterpret what you're reading. I start to read code, see that its assigning None to a parameter, and then a moment later have to re-interpret what we just read: None is not the argument, but the body of the function which is the argument. In linguistics that sort of thing is called a "garden path sentence" and research demonstrates readers take longer to comprehend them than sentences which don't require backtracking (re-interpretation). https://en.wikipedia.org/wiki/Garden-path_sentence Sometimes that's a good thing, if you're making a joke. But in general, they're not great for readability. Since your argument hinges on readability, that's a problem.
But at no point in reading "children.oldest().room" do you have to go backwards and re-intepret what you thought you saw. Even if the expression involves right-associative operators: children ** oldest ** room the worst that you have to do is defer thinking about children (push it onto the stack of short-term memory) until after you've thought about oldest**room. Now human memory has a very shallow stack. We struggle to hold more than approximately "seven plus or minus two" items in memory at a time. And of course people often forget that ** is right-associative (I know I do). But syntactically, there's no mental backtracking required. I'm not claiming that your suggested syntax is impossible in a LL(1) grammar like Python. I don't know. But I'm responding to your earlier assertion that it ought to always be obvious in context that you are looking at the body of a function, before you see the "with" keyword. As evidence for this assertion, you give examples where it is obvious: sort(sequence, by=card.suit with card) Sure, any English speaker familiar with the English idiom "sort by ..." can probably guess the semantics. That's great. But its not representative. We don't always have the luxury of expressions which read like English phrases: threading.Thread(target=None ... looks like the target is None, not a function, and we don't realise its not until we keep reading and learn at the very end of the expression that everything we saw before that point was part of the function body. It's great for English speakers that "sort by" appears in our code, but have a thought for those to whom it might as well be "pteg xb". Python is not just a language for English speakers, and if we're going to claim a readability advantage, we ought to at least acknowledge that not everyone will have that advantage, and not exaggerate the magnitude of that advantage by using words like "almost always".
There has never been a guarantee that expressions evaluate left to right simply by virtue of the fact that an order of operations exists.
That's fine, because I never said they did. It would be pretty foolish of me if I did, given that exponentiation is right-associative, and that we have comprehensions and ternary if expressions.
I know that. But you stated: "I was trying to say that the context almost always gives away that the reader should expect a function." The difflib example is a real, not made up, example that goes against that. The context "isjunk" sounds like it might be a flag, not a function, and the code x==' ' supports that interpretation right up to the moment you read "with x" part, at which point you have to re-interpret what you've been reading.
Indeed. I don't deny that there are expressions where if you truncate at a certain point, the code up to that point looks like a valid (sub-) expression of a different type: spam ∆ eggs If you truncate just before the ∆ you get a valid subexpression "spam" which may not be the same as the expression "spam ∆ eggs". But there aren't many places in Python where after truncating just before ∆, you interpret "spam" one way, but if you truncate after the ∆, you intepret "spam" a different way. Normally spam is spam no matter what follows it. In your earlier example ", " is a string, regardless of whether you have read up to the dot or not. Of course we could do this (LL(1) parser permitting) but the point I'm making is that this isn't a small change, and I don't think it will have the benefit you believe it will. The contrary: I think it will hurt readability, not help it. I think the benefit of moving the body of the function to the front is less than you think, and the cost of moving the syntax which distinguishes it as a function to the end greater than you think. I don't have objective evidence for these opinions, but I've tried as best as I am able to give the reasons why I believe this, and not just make it an assertion.
If you honestly don't understand my position at all. [...] then I guess I've never met anyone quite like you.
I'm a unique and special snowflake. https://i.imgur.com/W3ljlBg.jpg
I don't know how to communicate my point of view any better than I already have.
I understand your position. I just disagree with it.
When you are claiming an advantage, if that advantage doesn't actually apply, then its not an advantage, is it? I'm not going to stop using a valid argument just because you don't like it.
Good thing I didn't do anything like that. Abe, you are attacking a strawman. I didn't give made-up deliberately awful code. I took existing code from the standard library, and translated it to your proposed syntax. These "random chunks of code" are a non-issue. I never suggested examples like that, and I haven't seen anyone else do so either. -- Steve

Michael Selik schrieb am 14.08.2018 um 21:42:
This is supported by education research. Some light Googling found a study on the topic [0] that is consistent with my own observations.
OTx2, and no offence, but … this is supported by research as well. People tend to search just long enough to find the link that backs their … observations. :) Stefan

On 14 August 2018 at 16:42, Michael Selik <mike@selik.org> wrote:
"until after" != "forever". A jargon might be just an acronym, a word or few words, meaningless for someone who doesn't know what it means [sic], but even for this person the jargon is useful: he/she can look for information about it. Teaching the other way around to let the student grasp the "mechanical procedure" before its name doesn't change anything regarding the names. You can make everyone memorize the algorithm for adding base-10 whole numbers by hand without teaching the students words like "adding" or "sum", not even the "+" symbol. But it would be a confusion if you use any other symbol or word to replace these "maths jargon" ones, and you shouldn't avoid the socially used names/symbols just because you're teaching that stuff for kids who still doesn't know them. And I'm aware of students complaining they can't remember something they've learned (or simply they didn't know someone was talking about what they know, a communication issue) because they didn't know the name (not even for searching in the web, a dictionary, whatever...). I really regret that I complained when expressions like "modus ponens" and "disjunctive syllogism" were teached to me during a class in 2004, that day I thought these stuff were so obvious that they shouldn't have a name. Until I found, later, that I needed to know these names in order to understand some stuff I was reading. These names might had been hard to memorize, but they were better than arbitrary names that no one else happens to use. Some of my worst teachers avoided the proper jargon forever, not just "until after" definitions/examples. Several classes here in Brazil tries to teach some concepts by forcing everything to be in Portuguese, like an "ideology of full translation", and sometimes the translated names are meaningless (no social context external to the class uses them). I got somewhat angry when I found that a lot of stuff I knew had other names in every useful social context, and I know who/what I should blame for that. Terminology is the first step when going into a new domain... an example, marked as "Important unit", can be found at https://www.statistics-made- easy.com/introduction-to-statistics/ *This introduction will teach you all the basic terms of statistics. It is important to understand them well before studying the unit about organizing data. The lessons are organized in a way to make the learning process as smooth as possible. Follow the logical order given here to study the lessons.* [...] It's tempting to use terms based on the origin of the concept,
historical odds and ends, or even jokes. [...]
Usually, you're not naming something new and unnamed... but sometimes the concept might have more than a single name. I think that's like irregular verbs: they're so common that they "break the patterns"; concepts that are spread/scattered everywhere might have a distinct name in each domain. Names should be useful to precisely express the concept in social contexts, but there's a context that should never be considered for that: the "teaching" one. If the concept itself isn't known by some people, why care about an alternative "non-jargon" name? A name doesn't belong to a person or a class, but to the people who can use/understand it, and I believe using proper jargon instead of alternative "simplified" names should maximize that. It's the social expressiveness towards people who already know the concepts that should be emphasized, not some other arbitrary "simplification" goal (e.g. minimize the number of characters, only use English, ...). IMHO, avoiding jargon sounds like avoiding teaching. In the case of new Python stuff, avoiding the socially standardized terminology is an act of isolation/seclusion. -- Danilo J. S. Bellini --------------- "*It is not our business to set up prohibitions, but to arrive at conventions.*" (R. Carnap)

Michael makes some reasonable points, but I think the very premise of this thread is putting the cart before the horse. As educators, if we fail to teach the technical language of a field to our students, we are failing to prepare those students to enter that field. Technical jargon is the language of the field. If it makes teaching beginners more difficult, well, so it goes. Lots of things make teaching more difficult e.g.: - technical jargon; - expecting students to write code that runs; - expecting the code to run correctly; - having them do input validation and error handling; - and write documentation and comments for their code. Lambda is becoming a standard technical term in computing, even in languages which don't use that keyword. The official name for Java's anonymous functions is "lambda expressions": https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-Quick... Ruby has no fewer than three separate kinds of anonymous callable, blocks, procs and lambdas: https://medium.com/@AdamKing0126/ruby-whats-the-deal-with-procs-and-lambdas-... and the term is now used in C++, C#, LINQ and others, even if they don't use it as a keyword. https://duckduckgo.com/?q=lambda+expressions We should not focus too heavily on the earliest and most ignorant stage of people's programming life. That stage makes up probably less than 10% of their life as a programmer. Python is a general purpose programming language and we shouldn't shy from the appropriate use of technical terms in the documentation and the language itself. Python is not Scratch and the primary focus of Python the language is not education. Many people come to Python for the first time with one, two or ten other languages under their belt, and some of them even have a good grasp of computer science. We should not talk down to those experienced coders for the sake of those in the first year or so of their programming life. Scratch, for example, doesn't use the word "function" to describe functions. They use "blocks" (but not in the Ruby sense). This is, I suppose, fine for the average kid of age 8, if you think talking down to kids is okay (or necessary). But if we were designing Python from scratch today (pun intended), we surely ought not follow their lead. https://en.scratch-wiki.info/wiki/Custom_Blocks More comments below, following Michael's comments. On Tue, Aug 14, 2018 at 12:42:29PM -0700, Michael Selik wrote:
And the experience of educators like Chris teaching Javascript suggests strongly that no, it doesn't, since Javascript learners have just as much trouble learning the concept of "function" as Python learners have with "lambda". Chris' conclusion is that anonymous functions are inherently hard for many beginners to learn, regardless of whether the syntax is called "lambda" or "function". That matches my own observations, interacting with newbies on various mailing lists, as well as my own personal experience. I believe that many people have a lot of trouble grasping the concept of functions as first-class values capable of being passed to other functions as data. It requires a major rethink of the way we think of functions. We go from treating them purely as verbs: sort the list to nouns in their own right: process the sort # the what now? Not "process the sorted list", but reify the sort verb into an actual thing (an object or value) and then process that thing itself. This is mind-bending when you think about it, far more mind-blowing than the normal linguistic process of nouning verbs and verbing nouns. No wonder people take a while to get fully comfortable with the concept. It took me a long time to stop writing code like this: map(lambda x: len(x), sequence) instead of simply map(len, sequence). I doubt it would have taken any less time if it were map(function x: len(x), sequence) instead. Aside from having to learn the correct spelling ("lamdba"?) it was never the *name* that gave me trouble. Of course there is a cost for beginners to having to learn a name, and the less often the name is used, the longer it takes (unless it is extremely memorable). But that cost is paid for, with interest, later, as a journeyman or journeywoman programmer.
I agree. When I teach my students function transformations in maths, any time I use the technical terms translation, dilation and reflection, I follow up with the common terms shift, stretch, and flip, and vice versa. I make a point of always associating the imprecise plain English words with the precise technical terms. Nevertheless, it is important that I teach them the technical terms too. -- Steve

Hi Steve You and I have different experience, background and interests. You wrote
Python is a language with an enormous range. That is one of it's many strengths. Its users range from school-children, doing programming as part of their general education, all the way to research scientists, professional system administrators and the like. There are some really clever professional Python programmers. Some students learning Python, shock horror, won't enter the field. What proportion, I don't know. Some good statistics here would be helpful. For a different view of Python, take a look at * https://www.codeclub.org.uk/ * https://tutorial.djangogirls.org/en/python_introduction/ * https://codewith.mu/ * https://microbit.org/ * https://microbit.org/code/ The last two are important. 2016. All these children could be Python users. Very different from the students that you, as an educator, are preparing to enter the technical field of computer software. You further write
I'm very happy that Python works for the novice, and occasional programmers. Who have not aspirations to have a life as a programmer. Maybe they're musicians, or artists, or someone building a personal website. There are some really clever people in these fields, who write non-professional Python software. I'm very happy that Python works for high powered experts who are doing machine learning, numerical analysis, partial differential equations, big data and cloud system administration. To turn you statement around: We shouldn't focus too heavily on the latest and most learned stages of programming. Such activity, by hours spent, makes up probably less than 10% of humanity's time spent coding. Not disagreeing with you. Just viewing things differently. -- Jonathan

On 22/08/18 18:06, Jonathan Fine wrote:
Ditto for the Raspberry Pi, which is cheap rather than free but aimed at very must the same market.
In my experience teaching 12-15 year olds Python, not very different at all. Those that are interested in learning programming are interested in learning it properly, just like their older counterparts. Those that aren't interested in learning it aren't interested in learning it, no matter how much you dumb it down or talk it up.
If you're talking about Python coding I sincerely doubt that statistic. If you're talking about coding in general, it's meaningless. -- Rhodri James *-* Kynesim Ltd

On Wed, Aug 22, 2018, 12:40 PM Steven D'Aprano <steve@pearwood.info> wrote:
That long time is ongoing :-) You recently wrote in another thread: widget.register(callback=lambda: spam.eggs()) Instead of the slightly faster and definitely more direct: widget.register(callback=spam.eggs())

This isn't trying to snipe. I have written the exact same unnecessary circumlocution in my own code hundreds of times. Hopefully most of them simplified before release, but I'm sure not all. And I "wrote the book", as one says, _Functional Programming in Python_. Functions as sounds is a powerful but counterintuitive concept. On Wed, Aug 22, 2018, 1:38 PM David Mertz <mertz@gnosis.cx> wrote:

On Wed, Aug 22, 2018 at 01:38:03PM -0400, David Mertz wrote:
Hah, so I did.
Instead of the slightly faster and definitely more direct:
widget.register(callback=spam.eggs())
Except that doesn't work, since you are passing the result of calling spam.eggs as the callback, instead of spam.eggs itself :-) -- Steve

On Thu, Aug 23, 2018 at 6:24 AM, David Mertz <mertz@gnosis.cx> wrote:
This isn't quite the same, incidentally. It's (mostly) equivalent to: widget.register(callback=lambda *a,**kw: spam.eggs(*a,**kw)) I don't know of any situations where you specifically want to mandate that there be no arguments, but it's enough difference that I'd go check the docs before doing the refactor. (This is FREQUENTLY significant in JavaScript, where argument count mismatches are silent. So I'm used to seeing those shim functions.) ChrisA

Op wo 22 aug. 2018 18:40 schreef Steven D'Aprano <steve@pearwood.info>:
Civilization itself had trouble with the concept. Functions as mathematical objects in their own right were only conceived (late) in the 19th century. Church's lambda notation was the first way to write down a function without naming it, in the 1930's. And a proven consistent model for lambda calculus was only provided by Dana Scott in the 1970's! So clearly these mathematical developments haven't yet entered high school mathematics, which remains firmly set in an 18th century mindset, where we can interchangeably write down f or f(x). Unfortunately modern computer languages require more, so it is up to the comp sci teacher to fill the gap. But let's not blame Church's notation for that. λ f.(λ x. f(x x)) (λ x. f(x x)) lambda f: (lambda x: f(x(x))) (lambda x: f(x(x))) (Yeah I know it doesn't work in eagerly-evaluated Python). Stephan

Stephan Houben wrote:
Church's lambda notation was the first way to write down a function without naming it, in the 1930's.
That's debatable. It could be argued that calculus makes use of anonymous functions, e.g. the expression d/dx (x**2 + 2*x - 3) describes a function of x without giving a name to it. This means that
these mathematical developments haven't yet entered high school mathematics
is not entirely true -- anyone who's studied calculus has been exposed to the concept of an anonymous function, although it probably hasn't been explicitly described in those terms. -- Greg

Steven D'Aprano wrote:
I don't think it's all that much different. Consider the sentences: "Sorting is an interesting operation. It can be done efficiently or inefficiently." Here we temporarily bind the operation "sorting" to the pronoun "it". That's really the extent of processing that we do on functions. We don't actually do anything to the functions, we just give them temporary names. (Unless you go in for bytecode hacking or something, but beginners aren't going to be doing things like that.)
Is that because you found the concept itself difficult to grok, or did you just have trouble seeing opportunities to apply it? If you saw map(len, sequence) in someone else's code, did you immediately recognise what it was doing, or did you have to stop and think about it? -- Greg

[Steven D'Aprano]
It's not the responsibility of the tool to teach. My socket wrench doesn't have the history of socket wrenches inscribed on it, nor does it have any description of the different kinds of nuts and bolts. That's called the Single Responsibility Principal or SRP for short. Your job may be to educate, but that's not Python's job. [Steven D'Aprano]
We should not focus too heavily on the earliest and most ignorant stage of people's programming life.
The problem goes beyond just learning the term lambda, it can increase mental load on an already mentally demanding activity to have to translate an unfamiliar word every time you see it. It's lack of relation to anything else makes it hard to remember and hard to recall later. I've also argued that the very form of lambda expressions is noisier than it otherwise needs to be. It's not like noise is only distracting to novice developers. [Steven D'Aprano]
That stage makes up probably less than 10% of their life as a programmer.
My argument has never been about the high magnitude of the opportunity cost, just that there is one (IMHO) compared to a less jargon option. Better is better. period. Even if only improves the first 10% of your programming career. That's why I've said I don't ever think this discussion will lead to action. [Steven D'Aprano]
A Caterpillar Bulldozer is a professional piece of equipment. That doesn't mean they throw out basic tenants of good user interface design <https://en.wikipedia.org/wiki/Principles_of_user_interface_design> and take it upon themselves to teach the operator construction jargon through the interface. They still find it's better to use a red break light symbol with the aim of clearly communicating to non-experts. Just like a child's go kart! Even Python didn't find it necessary to teach me the word "ternary" for ternary expression. [Steven D'Aprano]
I don't think that one person's anecdotal evidence could be considered "strong" in the face of scientific studies. Especially when it's become clear that Chris was referring to a broad category of subjects that are only tangentially related to lambda expressions. [Steven D'Aprano]
That's not been my experience. [Steven D'Aprano]
Those topics have nothing to do with lambda expressions. You can demonstrate them without ever writing a lambda expression. The difficulty of those concepts doesn't inform the choosing of the name. You might as well name it "schubalu" and when I say "that's unnecessarily confusing" just say "well it's easier to learn the word 'schubalu' than it is to learn how Bloom Filters work!" Yup. I can't argue with that. I guess we should stick with "schubalu"... [Steven D'Aprano]
Aside from having to learn the correct spelling ("lamdba"?) it was never the *name* that gave me trouble.
Maybe not for you, but it's fresh enough in my mind that the name itself caused confusion. I know it seems minor, but back in the 'partial' thread, I was literally just talking about the name: lambda. Nothing else matters because it's all invariant. Callbacks will still be hard to learn. Functions as first class objects will still be confusing. All I'm talking about is a missed opportunity to choose a moderately better name. Just like function.partial vs. function.given. I didn't think my opinion would spawn 6 threads and hours of nit-picking. None of your discussion about the difficulty of functional programming informs the value of jargon over less jargon. When is it better to favor more common language, if ever? [Steven D'Aprano]
that cost is paid for, with interest, later, as a journeyman or journeywoman programmer.
Yeah, or never. My friend used to say he was in IT, then it was Dev Ops, now there's a new term. Or it may be that everyone knows what you mean when you say "anonymous function" and you didn't earn any interest for learning "lambda". After I graduated with my EE degree, I bought a bunch of vocabulary flash cards so that I could take the GRE and go to grad school. I remember wondering, "why the hell does every flash-card set have 'numismatics' in it?! I can never remember that damn word!" now I know it. It's never paid interest... [Steven D'Aprano]
Nevertheless, it is important that I teach them the technical terms too.
I find that beyond the basics: class, object, function, variable, argument, parameter, etc. Having students memorize jargon has limited value.

On Thu, Aug 23, 2018 at 10:44 AM, Abe Dillon <abedillon@gmail.com> wrote:
If the concept is utterly unfamiliar and the word is familiar, it creates a different problem: the false parallel. Let's suppose that, instead of calling them "lambda expressions", we call them "bacon expressions". Great! Lots of people know what bacon is. Is that an improvement? Definitely not. Some people love bacon and will wonder what anonymous functions have to do with their favourite food; others will wonder whether it's okay for a devout Jewish or Moslem person to use them. Technically this is true of "lambda" too, but for those who know Greek, it's like calling something an "S-expression", which is fairly obviously an abbreviation for something. ("Symbolic expression", I think? Someone might correct me there.)
Yes, you've asserted it. We've disputed it. You have yet to provide real evidence.
No, it probably called it an "if-expression" or "conditional expression" or something. "Ternary" just means it has three operands, so Python also has another very common ternary expression, namely the bounding: "5 < x < 10".
What broad category of subjects?
Okay! What's been your experience? Can you show us two comparable situations, one where you taught lambda functions in Python, and the other when you taught anonymous functions but without the word "lambda", and can demonstrate that one is harder than the other? My experience is that *highly intelligent* adult students, who have mastered many other concepts very rapidly, frequently have trouble with: * Asynchronous programming * Anonymous functions * The difference between serverside and clientside validation * How to debug code * Recursion

[Chris Angelico]
Or maybe "curry expressions!"... (I really hate that jargon too) I think this is a pretty ridiculous take on my argument. [Chris Angelico]
No. The lambda in lambda calculus was chosen arbitrarily. It has no deeper meaning. According to Dana Scott, who was a Ph. D student under Alonzo Church: The choice was "eeny, meeny, miny, moe" <https://www.youtube.com/watch?v=juXwu0Nqc3I&t=1m10s> [Chris Angelico]
Why isn't my example comparing the pseudo code: hand = sorted(cards, by=card.suit) to the actual code: hand = sorted(cards, key=lambda card: card.suit) suitable to at least demonstrate the basic idea? I can show you the noise right here: hand = sorted(cards, ke#=#############card.suit) I could come up with a hundred such examples if you need more "evidence" of my point, but I'm not interested in nit picking how one should properly represent or sort cards. I'm also not interested in discussing how I need to check my privilege because my proposal might not help Hellen Keller write better code. Maybe I should put you on the defensive and make you prove that it's always best to inject as much jargon as possible into Python and that there's no better form of lambda. We could be discussing this idea more deeply. Jonathan Fine pointed out some interesting ideas about this. But mostly you and D'Aprano seem interested in being contrarians and denying that there might be any hint of legitimacy to my point of view. I don't think it's unassailable, but it has nothing to do with the proper way to represent a wild-card in a poker simulation. [Chris Angelico]
it probably called it an "if-expression" or "conditional expression" or something.
I don't know how many times I have to reiterate this: I'm not talking about what humans call it. I'm talking about how it's expressed in code. [Chris Angelico]
What broad category of subjects?
* Functions as first-class objects * Callbacks & Event Handlers * Passing functions as arguments * the "semantics" as you put it In other-words, when you said: [Chris Angelico]
Whether you spell it "function(arg) {...}" or "lambda arg: ...", it's the semantics that are hardest to learn.
Those are orthogonal concerns! All else being equal, a descriptive name is better than a less descriptive alternative. It might not be on the same scale as the confusion caused by semantics, but it also doesn't have anything to do with the confusion caused by semantics. function.partial and function.given have the exact same semantics! We were literally only talking about names. Like I've said to D'Aprano: It may be way harder to drive a car than to buy windshield-wiper-solution for a car, but I can still prefer the name "windshield-wiper-solution" to "zeta" because calling it "zeta" just causes unnecessary confusion. Will it cause mass panic? Will it cause more car accidents? No. But, my goodness, you guys seem to want to talk a lot about that other stuff in order to convince me I'm wrong that "windshield-wiper-fluid" should not be called "zeta". I can't go two replies without you bringing it back up. It's really not worth the amount of words I've put into defending what I thought was a pretty reasonable POV. [Chris Angelico]
Okay! What's been your experience?
That students have trouble realizing that def f(x): return x*x is exactly the same as: f = lambda x: x*x yet have very little trouble learning how to write a function in JavaScript: f = function(x) { return x*x } Literally just that.

On Thu, Aug 23, 2018 at 11:59 AM, Abe Dillon <abedillon@gmail.com> wrote:
Because your form cannot possibly work without some additional information. How is "by=card.suit" supposed to ACTUALLY WORK? As soon as you make it work, you create extra noise all of your own - yaknow, like saying that "card" is a parameter to the function. So maybe it ain't just noise. I'm done arguing. You aren't listening. ChrisA

[Chris Angelico]
Because your form cannot possibly work without some additional information.
That isn't my form. That's PSEUDO CODE. Just like I wrote above it. You're the one who's not listening. The alternative I've suggested, for the thousanth time, is: hand = sorted(cards, by=card.suit with card) or hand = sorted(cards, by=card.suit with(card)) The noise compared to the PSEUDO CODE looks like this: hand = sorted(cards, by=card.suit ##########) Which, to me, is preferable to: hand = sorted(cards, ke#=#############card.suit) You need me to type that out a few dozen more times?

On 2018-08-23 03:10, Abe Dillon wrote:
You're complaining that it's "noise", but I think you need a bit of noise to tell you that it's defining a function, otherwise you'll see an expression and think it's evaluated immediately, but then you'll see the "with" at the end telling you "oh, by the way, this is a function, so don't evaluate it now". You gave an example in JavaScript and said that students had "very little trouble" with it, but notice how the function itself began with a reserved word. If you're complaining about the word "lambda", that's fine, but if you're complaining about where the arguments should go, then I'm afraid I'd have to say you're wrong.

Let me preface this by saying: I've already addressed the possibility of a form that tells you up-front that it's a function Granted it was 8 replies ago and at the end of a long-winded response, so I'll summarize here: A format like <PREFIX><EXPRESSION>[<SEPARATOR><SIGNATURE>] would, in my view, be preferable to a format that puts the signature first. An example might be: hand = sorted(cards, by=def card.suit with card) hand = sorted(cards, by=return card.suit from card) hand = sorted(cards, by=(:card.suit with card)) # the happiest form! hand = sorted(cards, by==>card.suit :: card) # eh... etc... There are many possibilities. [MRAB]
You're complaining that it's "noise", but I think you need a bit of noise to tell you that it's defining a function
I feel like the pseudo code example shows that at least isn't *always* true. Yes, the noise is neccessary for the computer's sake, but it doesn't have to go in-front of the logic. It's usually not that important for the reader. The intent is to sort cards by suit, not to declare a function that gets the suit of a card. The fact that you have to declare a function is secondary to the intent. If it were up to me, I'd make "by" the keyword for a key-function in sorted, sort, min, max, etc. and have special secondary keywords for simple, common cases:
[MRAB]
That's true of most expressions:
Assuming you know that grades.get is a method, you don't know that the expression passed to 'key' is a function until you read the whole expression. If you don't know what grades.get is, you don't know what kind of object is being passed to key:
best_student = max(spam, key=spam.eggs)
Is it catastrophic that you don't know what ham.eggs is? Is it something to do with card.suit with card being a literal that makes you demand to know what type of thing is being passed before you finish reading the expression? Because that clearly isn't true in the case of variables. Besides; you usually have several context clues leading up to the 'with' : 1) The function (if you're familiar with it) 2) The name of the function (if it's well named and you are familiar with the name) e.g. add_callback, add_handler, on_mouseover, etc.. 3) The name of a keyword parameter (if it's well named and you're familiar with the name) e.g. key, callback, handler, event_handler, filter, etc... 4) The usage of a variable that has yet to be declared (just like in generator/comprehension expressions) example: def best_hand(cards): hand = sorted(cards, key=card.suit with card) ... My hunch is that the vast majority of cases satisfy enough of those that reading a 'with' would rarely be all that surprising. I also assert that some of those conditions are far more critical to comprehending code, so if they're missing, your comprehension ends long before you're "surprised" by the appearance of a 'with'. All of the arguments in the following are clearly declared literals: foo = bar.baz(100, True, ham="spam") Can you read that? In a sense, yes. Can you comprehend it? No! What if I asked you "where's the bug?". Nope. Another example (from D'Aprano): sm = difflib.SequenceMatcher(isjunk=True) t = threading.Thread(target="hello") Now imagine that none of the 4 context clues above are true. Can you read those? Can you see the bugs? Is there even a point to reading beyond where your comprehension stops? If you don't know anything about what's expected for "target" or "isjunk" than reading any further isn't helpful. Knowing that "hello" is a string right away saves you no pain. The paramount problem is that you don't know that it's supposed to be a function. You need to stop when you loose comprehension and read the docs. Then when you come back, you'll know that 'isjunk' should be a function. The counter that there may be cases where none of the 4 context clues above exist indicates a more urgent problem than knowing the types of literals being passed (immediately or otherwise). Also, by the time you hit the "with" it's not like the "new information" requires you to look back and re-examine anything. It's just new information like any other compound statement:
[MRAB]
Yes, that was the context of the discussion I was referencing. Just the word "lambda". In this ongoing discussion I've declared on two separate gripes: 1) the word itself and 2) the format. I think a different format opens up other possible word choices, but that's not really important.

Chris Angelico wrote:
Yes, except that lambda is an even more arbitrary choice of letter -- as far as I know, it doesn't stand for anything. The story goes that, in his handwritten notes, Church used something like a caret or circumflex. When his work was published, the typesetter either misread it as a lambda or subsituted a lambda because it was the closest thing he had in his font, and from there on it stuck.
If we wanted to be true to the original we should call them "caret expressions" and write ^(x, y): x + y Nice and quiet! -- Greg

On Thu, Aug 23, 2018 at 05:55:13PM +1200, Greg Ewing wrote:
If you go back far enough, pretty much all words and written symbols are arbitrary. The word "dict" can be traced back to the Latin for "to say". Where did the Romans get their "dico" from? Linguists have extrapolated back to the hypothesised Proto-Indo-European word déyḱti (“to show, point out”). At this point, we can't even begin to guess where that word came from, but we can be sure that at some stage of human pre-history, it began as an arbitrary set of sounds. Many thousands of years later, it now means a hash table in Python. The only difference between dict and lambda is time. Lambda's arbitrariness is less than a century ago, while dict's is lost in the mists of prehistory. Why should that make a difference to anyone but a linguist? As I posted earlier, lambda has become a standard term, used by boring, staid, non-functional languages like Java and C++. There's nothing function-like about "lambda", but there's nothing function-like about "function" either. -- Steve

[Steven D'Aprano]
If you go back far enough, pretty much all words and written symbols are arbitrary.
I think this is wandering into nihilistic pedantry. Go back or forward far enough (or zoom in or out far enough) and nothing means anything. When I first learned Python, I had never heard the word "tuple" but as soon as I saw it, it made sense to me. It comes from the latin suffix for adjectives relating to multiples of things: "-uple" It's been around long enough to make its way into many common words (triple, tuplet, multiple) and many languages. That context makes it easy to remember. My guess is: even if you've only learned basic English, you have a far greater chance of being able to remember the meaning "tuple" over "lambda". Possibly even if you've never learned English, your chances of being able to relate "tuple" to relevant concepts is higher than being able to anchor "lambda" to anything relevant. [Steven D'Aprano]
As I posted earlier, lambda has become a standard term
I would agree that it's become a known term among computer scientists and maybe even the majority of professional programmers, but: 1) There are several terms commonly used interchangeably for the same concept including 'anonymous function', 'function literal', even 'deferred expression' works in the context of Python because the implementation only allows for a single expression (or implicit return statement?). So I don't think it has been standardized in the sense that it's the one, agreed upon, term. 2) being known of, does not equate to being well known. I've heard of a "busy beaver", but I couldn't tell you off the top of my head what it is. Lay people have heard of and talk about DNA or genes or genetics, but if you ask them what a codon is, most people's faces will go blank. The jargon of genetics is known about only in vague terms. 3) You've provided documentation from several languages to show that the term is used, but have you compared that to the usage of other terms? 4) Sometimes standardized terms can still be warty. There are plenty of terms in Science and Engineering that have confused roots and confusing consequences, but are too ingrained to abandon. The term "Rare Earth Metals" was coined in the late 18th century even though many of the elements are quite plentiful. Anonymous function or function literal are actually descriptive. Why not back those horses? [Steven D'Aprano]
There's nothing function-like about "lambda", but there's nothing function-like about "function" either.
I'm not sure what you mean by that.

Steven D'Aprano wrote:
The only difference between dict and lambda is time.
Well, "more arbitrary" was perhaps a rather loose way of saying it. What I meant was that the chain of associations is shorter for "lambda" than for "s-expression", because the "s" refers to a word the reader is probably already familiar with, but "lambda" doesn't refer to anything pre-existing that's semantically related. Not that there's anything wrong with that -- mathematicians love to endlessly re-use the same rather small set of symbols, so sometimes they have to make a completely arbitrary choice. -- Greg

Abe Dillon wrote:
They still find it's better to use a red break light symbol with the aim of clearly communicating to non-experts.
The handbrake warning light on my dashboard has a symbol that represents a brake drum and a pair of brake shoes, and the word "BRAKE" written underneath it. That's a technical term and an implementation detail, right there in the user interface! (Never mind that the implentation detail isn't accurate, because the car actually has disc brakes...) -- Greg

On Thu, Aug 23, 2018 at 03:12:30PM +1200, Greg Ewing wrote:
Indeed. I wonder whether Abe drives, and if he does, whether he has read the owner's manual. They are typically *full* of jargon. Similarly for bulldozers. Here's a short instructional video: https://www.youtube.com/watch?v=p2mh6kUuedk Many of the controls are described in common terms (why would they need jargon terms for "forward", "reverse", "left", "right"?), but they also mention specialist jargon like "throttle" and "decelerator". A bulldozer has perhaps as many as a dozen critical functions: move forward, reverse, lift the blade, etc, which can only combine in a rather limited number of ways. The user-interface is designed for real-time manual operation. Programming languages have multiple dozen features, hundreds if you include Python's std lib, which combine in a near-infinite number of ways. Programming is a batch operation: while a bulldozer operator has to react on the spot, the programmer typical gets to think ahead, write some code, think some more, write a bit more, do some incremental tests, write some more code, do some research, write a bit more code, think some more etc in dozens or hundreds of iterations before actually running the code in production. I don't think its productive to compare programming to driving a bulldozer. A better analogy would be sound mixing: https://videohive.net/item/sound-mixer-2/2244660 https://www.soundonsound.com/sound-advice/glossary-technical-terms -- Steve

[Steven D'Aprano]
Indeed. I wonder whether Abe drives, and if he does, whether he has read the owner's manual. They are typically *full* of jargon.
Do you still not understand the difference between documentation and interface? You seem to not even acknowledge that there's a difference between how one talks about a tool and how one uses said tool. Typically, the main concern of someone making a complex tool like a bulldozed is that the interface is as clear, accessible, language agnostic, simple, and utilitarian as possible. The reverse noise is a simple beep, not a voice saying "throttle set to reverse position". You use levers and buttons typically labeled with symbols rather than words. There are reasons why designers favor symbols and indicator lights over technical jargon. It has nothing to do with kiddie design vs. professional tools. It has everything to do with favoring the most intuitive interface possible to get work done. I honestly don't know what to say anymore. You keep conflating the syntax of Python with documentation and human-to-human communication. It's incredible. I don't know how many times I need to point out the difference. Do you think python's conditional operator should be like this: z = ConditionalOperator(predicate: x==y?, affirmative: x*2, negative: None) ? What can I do to illustrate that there is, indeed, a difference between what people call something and how someone uses a tool? I'm at a loss for words. On Thu, Aug 23, 2018 at 12:21 AM Steven D'Aprano <steve@pearwood.info> wrote:

TL;DR - I accept that there've been a few cases where I could have chosen my words better, and consequently I've rubbed Abe the wrong way; sorry about that Abe, as I said earlier (and I meant it) I have no grudge against you. - The most important technical issue I wanted to get from my discussion with Abe has been solved, I now believe that I understand what harm he feels was caused by chosing the name "lambda" over some alternative. - Namely (if I have understood Abe correctly) its the lost opportunity to have a better name. - Which seems to me to be so slight a harm that I don't think it gives us any guidance at all as to whether "partial" or "given" would make a better name for this proposed feature. (So much drama for so little gain.) Even after all these years of seeing people over-react to minor perceived slights (whether real or not), I cannot believe how quickly this one has degenerated into antagonism and over-reaction, and over so little. It certainly has not been helped by people fanning the flames of argument by calling this a "toxic forum". We should assume good faith. Before flying off the handle and taking offense, we should assume misunderstanding (on either or both party), accidental poor choice of wording, or merely robust debate rather than malice. We ought to be careful about making assumptions about people's motives from their responses. Email is a notoriously bad medium for judging people's motivation. The rest that follows is detail, responding to a few specific points which I deem relevant but not essential. * * * On Sun, Aug 12, 2018 at 10:31:36PM -0500, Abe Dillon wrote:
I explained my position on lambda as fully as I care to in my response to Niel if you care to read it.
I did read it. Just because I didn't respond to it directly doesn't mean I didn't read it. You say you object to the name, but then suggest a change that is idependent of that name. You talked about the placement of the function signature, wanting to put the body of the lambda first, before the parameter list. That has nothing to do with the choice of name "lambda", which is what I thought you were objecting too as it was too jargony. Moving the parameter list to the end of the expression is idependent of the keyword "lambda".
Nobody has accused you of frothing at the mouth. You seem to be talking about "opportunity costs" in a sense. Its not so much that the name lambda does harm in and of itself, but that another choice could be *even better* and do *even more good*. Is that a reasonable description of your position?
My original post was agreeing with you. Supporting your own words. If you don't agree with my position that we should avoid jargon for jargon's sake,
And don't imagine for a second I'm not aware of the irony.
I meant exactly what I said. *Possibly* a less jargon name would be nicer. Or possibly not. I was opening the issue up for further discussion, not nailing my colours to the mast as champion for the idea.
What about my saying it all of a sudden makes it an "extreme overreaction"?
Now you're quoting me out of context. It was your claim that the name "lambda" does harm to Python that I described that way. In hindsight, I wish I had left off the adjective "extreme". [...]
Notice: I never said "real, significant, non-trivial harm" anywhere in this entire discussion.
In fairness, you did say "minor" harm, so I'll accept that my emphasis on real significant etc was questionable. I don't know where the boundary between minor and trivial lies and I think people can disagree on this point. So I'll accept that here I read more into your words than were actually there. Sorry about that. [...]
That's not what I wrote. There's a difference between these two positions: - needing to learn to read English words to use Python; - using Python is the only reason to learn English. I said the first, not the second.
Where it comes from is not really important. Words change and are co-opted in new contexts. "Lambda" is rapidly become a standard programming term, and language agnostic, e.g.: https://martinfowler.com/bliki/Lambda.html -- Steve

[Steven D'Aprano] > - I accept that there've been a few cases where I could have > chosen my words better, and consequently I've rubbed Abe > the wrong way; sorry about that Abe, as I said earlier (and > I meant it) I have no grudge against you. Thank you. I hold no grudge against you either. I'm sorry for all the drama. [Steven D'Aprano] > - The most important technical issue I wanted to get from my > discussion with Abe has been solved, I now believe that I > understand what harm he feels was caused by chosing the name > "lambda" over some alternative. > - Namely (if I have understood Abe correctly) its the lost > opportunity to have a better name. Yes. That's pretty much it. In hindsight, I should have realized that the word "harm" carries a much more sever context in the programming community given all the "X considered harmful" articles out there. [Steven D'Aprano] > - Which seems to me to be so slight a harm that I don't think > it gives us any guidance at all as to whether "partial" or > "given" would make a better name for this proposed feature. I consider jargon for jargon's sake to be a poor reason to choose one term over a much more common term, however; I don't consider all jargon equal. I think "anonymous function" is far more descriptive than "lambda". I think you're ultimately right, however; that this doesn't guide the decision of "partial" over "given" very much because "partial" is not all that obscure. "partial function application" is fairly clear and as you said, Python wouldn't be trying to create an association from scratch. [Steven D'Aprano] > It certainly has not been helped by people fanning the flames of > argument by calling this a "toxic forum". At that point I felt like I had expressed that you came off as antagonistic toward me, had my feelings brushed off, then had multiple people ganging up on me about something I thought I had clearly articulated. I don't want to start a big fuss about it, but now both you and Stephen Turnbull have not-so-subtly referred to me indirectly like this. This time is fairly benign, but Turnbull's remark comes off as a passive-aggressive way of calling me toxic. I hope this isn't a sign of things to come where it's fine to passive-aggressively sling mud, but being direct is considered "crossing the line", because I find passive aggression far more insulting. I'm not an eight-year-old and people hiding behind the plausible deniability that even thinly veiled passive aggression affords them frustrates me. As I said early on: I'd rather resolve issues than have them continue to fester. Passive aggression does the exact opposite. [Steven D'Aprano] > We should assume good faith. Before flying off the handle and taking > offense, we should assume misunderstanding (on either or both party), > accidental poor choice of wording, or merely robust debate rather than > malice. We ought to be careful about making assumptions about people's > motives from their responses. Email is a notoriously bad medium for > judging people's motivation. > The rest that follows is detail, responding to a few specific points > which I deem relevant but not essential. Those are wise words and I'll try to adhere to them in the future. I would like to amend, that when someone signals that they feel like you're being aggressive towards them, it's a good idea to apologize. It's a simple act that can diffuse a lot of tension. [Steven D'Aprano] > > I explained my position on lambda as fully as I care to in my response to > > Niel if you care to read it. > I did read it. Just because I didn't respond to it directly doesn't mean > I didn't read it. I didn't mean that as an accusation that you hadn't read it. I'm sorry it came off that way. [Steven D'Aprano] > You say you object to the name, but then suggest a change that is > idependent of that name. Yes, I can see how that could lead to confusion. I'm sorry. I do, indeed, have two mostly separate objections to 'lambda': 1) I think it's a bad name 2) I think it's a sub-optimal form The only relevance of the form is that it sort-of illustrates a broader name-space to explore. For instance, the alternative name 'def' doesn't really make sense in the reversed order: hand = sorted(cards, key=def card: card.suit) # this kinda works, at least I think it's better than 'lambda' hand = sorted(cards, key=(card.suit def card) # this is... not as good [Steven D'Aprano] > > [Steven D'Aprano] > > > > > How can we insist that 3/4 of the world learn English words to use > Python > > > > Do you really think that 3/4 of the world learns English just to write > > Python? > That's not what I wrote. There's a difference between these two > positions: > - needing to learn to read English words to use Python; > - using Python is the only reason to learn English. > I said the first, not the second. I don't mean to come off as combative, but that is a direct quote, and I didn't try to take it out of context. If I did take it out of context, then I'm sorry. My point was that (and I may be wrong about this) I don't imagine most non-english speakers who want to write Python learning just enough English to write python. I imagine that most of them learn a broader vocabulary and thus, discussions about common English words still apply to them. It would be interesting to know either way, so maybe we should have a poll? I don't know.

Hello, Currently the user defined functions are mutables, there can be existed python codes like this:
Adding a new method to function object can break existing projects, but it is without impact with buit-in functions because they are immutables. 2018-08-09 18:59 GMT+02:00 Michel Desmoulin <desmoulinmichel@gmail.com>:

Le sam. 11 août 2018 à 10:34, Vincent Maillol <vincent.maillol@gmail.com> a écrit :
Or use a decorator like in the lib ? from funcoperators import partially @partially def f(x, y): return x-y g = f.part(4) g(5) The mutability solution however cannot have a "self" argument : def f(x,y): return x-y f.stuff = lambda self: self(5, 2) f.stuff() # missing self One would have to give "f". f.partial = lambda *a, **b: functools.partial(f, *a, **b) g = f.partial(4) g(5)

Therefore one can do a decorator that gives .partial: def partialize(f): from functools import partial f.partial = lambda *a, **b: partial(f, *a, **b) return f @partialize def f(x,y): return x-y g = f.partial(5) g(3) That's the same idea as funcoperators.partially but doesn't return a new function (which has the advantage of keeping help(f)) Le sam. 11 août 2018 à 14:53, Robert Vanden Eynde <robertve92@gmail.com> a écrit :

Michel Desmoulin schrieb am 09.08.2018 um 18:59:
Except that this only works for functions, not for other callables. Meaning, code that uses this for anything but its self-defined functions will break as soon as someone passes in a callable object that is not a function. Stefan

On Mon, Aug 13, 2018 at 07:46:49PM +0200, Stefan Behnel wrote:
That's an excellent point. If it were important to cover those use-cases, we could add a partial method to types, methods, builtin-functions etc. But I suspect that doing that would increase the cost of this proposed feature past the point where it is worthwhile. Do we often call functools.partial on arbitrary callable objects that we don't know in advance? (Not a rhetorical question.) I know I don't -- all the times I've called partial, I've known what the callable was, and it was always a function I created with def. But maybe others do something differently. I don't mind writing this: # only a minor inconvenience spam = func.partial(arg) eggs = functools.partial(callable, arg) given that I knew upfront that func was a function and callable was not. But if I didn't know, the utility of a partial method would be hugely reduced, and I'd just use functools.partial for everything. -- Steve

Do we often call functools.partial on arbitrary callable objects that we don't know in advance?
For my part, I don’t think I’ve ever used partial in production code. It just seems easier to simply fo it by hand with a closure ( Am I using that term right? I still don’t quite get the terminology) And if I had a callable class instance I wanted to “customize”, I’d likely use an OO approach — parameterize the instance, or subclass. So yeah, partial is probably used primarily with “regular” functions. But then, I don’t know that we need any easier syntax anyway — maybe I’d be more likely to use it, but it kind of feels like a feature that’s there so we can write more functional code for the sake of writing more functional code. If someone’s really interested in this, a search on gitHub or something to see how it’s used in the wild could be enlightening. -CHB

I'd like to push for the less jargon-y `func.given()` version if this gains traction. Not only is it shorter, it's a much more common term with a clear meaning. Words like 'partial', 'curry', 'lambda', and 'closure' are fine for text books, published papers, and technical discussion, but I think they would (or do in the case of 'lambda') harm Python. I know the correct term for the 'if-else' expression is a 'ternary' expression, but that doesn't mean Python should have used the word 'ternary' in the syntax. On Thu, Aug 9, 2018 at 12:14 PM, Neil Girdhar <mistersheik@gmail.com> wrote:

I prefer partial since many programmers studied computer science, and also it makes the concepts easier to google. Anyway, I don't actually want either a partial member nor new syntax for this, but if I had to choose, I'd choose no new syntax. On Thu, Aug 9, 2018 at 2:32 PM Abe Dillon <abedillon@gmail.com> wrote:

On Thu, Aug 09, 2018 at 01:32:00PM -0500, Abe Dillon wrote:
It's a clear, *generic* meaning that doesn't have any association with partial application. https://www.google.com/search?q=function+given We'd be trying to create that association from scratch.
Words like 'partial', 'curry', 'lambda', and 'closure' are fine for text books, published papers, and technical discussion,
And programmers. Programming is a technical skill with its own jargon. Classes, inheritence, exceptions, trampolining, processes, threads, protocols, imports, decorator, builders... we are happy with all those, why should we fear partial and lambda?
but I think they would (or do in the case of 'lambda') harm Python.
That's an extreme overreaction. Do you mean to imply that there are people who looked at Python, loved the language, but decided to use something else because they didn't like the choice of the keyword "lambda"? If not, in what way is Python harmed? Would it be faster if the keyword was "function", or use less memory, or more expressive? Remember that to millions of programmers in the world, "function" is just as much an obscure foreign piece of jargon they have to memorise as "lambda" is to English-speakers. -- Steve

[Neil Girdhar]
I prefer partial since many programmers studied computer science
Many did not. I studied electrical engineering and wouldn't have been able to tell you what the word 'partial' meant four years ago even though I've been programming in one form or another since the late nineties. Many programmers are scientists, engineers, financial analysts, etc. I'm pretty sure I know what a closure is or what currying is, but if you put me on the spot, I'd probably turn to Wikipedia to make sure I don't screw up the definition. [Neil Girdhar]
It makes the concepts easier to google.
That can be an important criteria, but it can also be a red-herring. If an implementation is clear enough, few people would have to google it. If, however, you use obscure enough words like "lambda", people will google it every day and still find it confusing. The ternary expression is difficult to google if you don't know the jargon "ternary", but there's less of a need to google it because it's pretty obvious how it works based simply on its implementation. [Steven D'Aprano]
Sure, that's a good point. I don't think that sounds like such a big problem, but I also don't hate 'partial'. I just prefer 'given'. At any rate, I don't find the google-ablilty argument super strong because there are many constructs that are difficult to google, but still pretty great (e.g. comprehensions). [Steven D'Aprano]
Yes, technical discussion among programmers. [Steven D'Aprano]
I get that programming carries it's own jargon and I understand that it has a beneficial function. It can facilitate concise communication of nuanced concepts. It can also be a needlessly confusing way to convey otherwise simple concepts. In the latter case, it can feel like the intent is to create an air of superiority through esoteric language. I feel like "curry" and "lambda" are needlessly un-descriptive and confusing. "partial" really isn't that bad, I just prefer "given" because I think it's pretty clear. I've never heard of "trampolining", but if I had to guess: it's probably related to recursion that involves more than one function? I suspect that most programmers couldn't describe the difference between a type and a class. I suspect that most programmers couldn't tell you the difference between an exception or an error. I know that lots of programmers refer to the "__init__" method as a "constructor" instead of an "initializer". Precision is less of a problem In a programming language. `func.given` doesn't have dozens of possible meanings. It's meaning has to be completely unambiguous to the machine. [Steven D'Aprano]
Extreme? I thought it was a rather benign opinion. I'm not exactly frothing at the mouth here. It's not like I'm declaring holy war on Python for using the word 'lambda'. I just think it was a mistake (and thatdeath should come to all non-believers). [Steven D'Aprano]
No. Not at all. Is that what you got out of my sentence? Am I really the one being extreme? [Steven D'Aprano]
If not, in what way is Python harmed? Would it be faster if the keyword was "function", or use less memory, or more expressive?
I didn't realize I'd hit such a nerve. I think there are better ways that anonymous functions could have been implemented. I've already said in past discussions, I think the expression should come before the signature because the signature is often obvious from context so placing it before the logic is kinda noisy. I don't know what the best syntax would have been, but I refuse to believe that an esoteric word from an esoteric branch of calculus with an arbitrary etymology was the absolute best choice available. I think the harm that choice caused is relatively minor, but I don't think it was a great choice. I'm truly sorry if I hurt your feelings. [Steven D'Aprano]
Maybe we should use Egyptian Hieroglyphs then. Even the playing field. It doesn't matter anyway, right? It's all nonsense to someone... Honestly, I don't think 'partial' is that bad. I just wanted to support your own comment: although possibly a less jargon name would be nicer:
add1 = add.given(1)
But you seem to have some grudge against me. I don't get all the outrage over what I thought was a fairly benign post. Did I do something to make you so angry at me? I'd like to resolve whatever it is instead of having to deal with this every time I post. On Fri, Aug 10, 2018 at 2:09 AM, Steven D'Aprano <steve@pearwood.info> wrote:

On Fri, Aug 10, 2018 at 6:21 PM Abe Dillon <abedillon@gmail.com> wrote:
Not that it matters, but comprehension is a standard term in mathematics and computer science apparently: https://en.wikipedia.org/wiki/List_comprehension https://en.wikipedia.org/wiki/Set-builder_notation
I didn't think you were being extreme at all. I think you're making a reasonable point about keeping things simple. I disagree with you though when it comes to avoiding the technical terms. It's easier for people new to a field to learn the jargon of that field than it is to try to make it easier for them and by essentially creating a whole lot more technical jargon. (Even if that jargon uses common words.) Your idea for "given" isn't obviously doing a partial function application. Someone might wonder if "given" is setting thread local storage, or setting attributes on a callable class, or opening context managers at call time…

[Neil Girdhar]
https://en.wikipedia.org/wiki/List_comprehension https://en.wikipedia.org/wiki/Set-builder_notation
The point I was trying to make is: If you were to read a set comprehension for the first time, not knowing what it was, what would you google? It's not an easily searchable construct, but it's still an elegant, fairly easy to comprehend feature. This is actually a pretty good example of where I stand. Of course we use words like 'comprehensions' when talking about language features, partly because it's easier than "that expression that builds a list, set, or dictionary" and partly because we often discuss how other languages implemented the same general feature. That doesn't mean that the syntax has to contain the word 'comprehension': make_initials = lambda person: "".join(generator(domain=person.names, predicate=bool, term=lambda name: name[0])) initials = list.comprehension(domain=people, predicate=lambda person: any(person.names), term=make_initials) Borrowing from math notation and/or jargon, as comprehensions do, is fine, especially if it's common enough to be taught in grade-school. Set-builder notation is beyond what I learned in grade-school, but Python does more than 'borrow' from set builder notation. It uses familiar words like "for", "in", and "if", in place of that little epsilon (∈) and bar and logical conjugation operator (*∧*) which I think help make them understandable. [Neil Girdhar]
I'm willing to concede that that's probably true in this case. I think the term "partial function application" is fairly clear rather than jargon-for-jargon's sake. I could see someone thinking it meant that the function is partially run, but that's a pretty minor worry. I'm sure without looking it up, people would assume all sorts of things about what func.given could mean. I also think the case of someone running into either usage without some pretty glaring context clues about what's going on is pretty unlikely. I won't concede that lambda was an optimal choice. Even a reuse of the keyword "def" would have been better because it would clearly relate it to function declaration: hand = sorted(pocket + community, key=def card: card.suit)[-5:] It's literally short for "define function", so it makes sense. My other complaint about lambdas, that they should be arranged logic first, does go against pretty much all other implementations of anonymous functions <https://en.wikipedia.org/wiki/Anonymous_function#Examples>, but I still think it makes more sense: hand = sorted(pocket + community, key=card.suit from card)[-5:] There are several possible variations of that concept. I think most of them would be better than the current syntax. An alternate form of lambda is probably never going to come and I'm OK with that. It's just my go-to anti-jargon example. Anonymous functions are not a confusing concept, yet people get caught up on it surprisingly frequently. I think the name is partly to blame. On Fri, Aug 10, 2018 at 5:42 PM, Neil Girdhar <mistersheik@gmail.com> wrote:

Answering a few of Abe's comments out of order... On Fri, Aug 10, 2018 at 05:20:25PM -0500, Abe Dillon wrote:
Have we become so sensitive to disagreement that criticism of ideas is immediately seen as "angry", "a grudge", "outrage"? If so, I find that sad and worrying. My feelings aren't hurt, you haven't hit a nerve, I'm not angry at anything you wrote, and I'm not holding a grudge. I thought we were discussing *ideas*, not attacking each other. Just because I challenge your statements doesn't mean I'm attacking you. Moving on... [...]
I suspect that most programmers couldn't describe the difference between a type and a class.
In Python, there is none. There is a sense in which types are different from classes, but that sense is not fundamental, and in practice many languages blur the lines between them.
I suspect that most programmers couldn't tell you the difference between an exception or an error.
There's a school of thought that most programmers can't program. https://blog.codinghorror.com/why-cant-programmers-program/ But regardless, we don't design Python based on the misunderstandings of the least competent, most ignorant demographic. That's why we have exceptions, only some of which are errors, and not StopIterationError KeyboardInterruptError SystemExitError etc. I believe that using a well-designed language should gently encourage the programmer to learn, by example. I didn't know the the functional programming techniques of map, reduce or partial until I came across them in Python. I think I'm a better programmer and less ignorant now than I was for that. Consequently, when I hear you describing how few programmers know the term "partial", what I think is "what a great opportunity for them to learn something new!". Or not, of course. For those of us who don't care for functional programming idioms, there's no need to use partial in our own code.
Yes, that's what I got out of your sentence. If you don't mean that, I don't know what you do mean. You've said that the choice of keyword, "lambda", has caused harm. Given the chance to clarify what you meant, you stood by your comment that the choice of keyword "lambda" has done real, significant, non-trivial harm to Python (the language, or the community). Presumably you fear the same thing will happen again if we choose "partial" (otherwise, why raise the issue?). Harm in what sense? That's what I tried to ask earlier, perhaps not as clearly as I intended. If the choice of name "lambda" doesn't repel would-be users, or cause bugs, or harm performance, then what harm does it do? This is a genuine question. I'm trying to understand your comments, not just dismiss them. You made a comment much stronger than merely "I don't like the name", claiming that the name is harmful. I could just dismiss your comment as meaningless hyperbole and ignore it, but I thought to give you the respect of assuming that you might be correct but I just wasn't understanding why. Hence my question.
No, we ought to stick to ASCII, for reasons I've discussed recently in other threads. And Python does have a long-standing tradition of sticking to mostly English words, a tradition for which I personally am grateful. But we ought to "check our privilege", as they say. I think that if we as a community automatically reject any word because it isn't "plain English", that would be a sign of unexamined privilege and quite rude to boot. How can we insist that 3/4 of the world learn English words to use Python, if we aren't even willing to move out of our own comfort zone to the extent of learning accurate jargon terms from our own profession? None of this is to rule out "given". (I think it's certainly better than Perl's choice of "assuming".) But if we go down this path (which is by no means decided!), and choose "given" over "partial", we ought to be clear about the reasons why. -- Steve

[Steven D'Aprano]
Just because I challenge your statements doesn't mean I'm attacking you.
No. Telling me I'm having an extreme overreaction means you're attacking me. Pushing the narrative that I'm irrational by enumerating the least charitable interpretations of my words possible then claiming you were just discussing *ideas* is disingenuous. I don't know who you think you're kidding, Steven. You could have simply asked me what I meant. It would have been much easier. All those extra words serve a very clear purpose and everyone knows it, so you can stop acting "sad and worried" when someone calls you out. I explained my position on lambda as fully as I care to in my response to Niel if you care to read it. I only think lambda harms Python in so far as there were better alternatives that communicate their intention much better and are more readable. That's an opinion. If you must know, i'm not currently frothing at the mouth as I state it. My original post was agreeing with you. Supporting your own words. If you don't agree with my position that we should avoid jargon for jargon's sake, then what exactly did you mean when you said, "although possibly a less jargon name would be nicer?" Can you articulate why you think it might be nicer to use a less jargon name? What about my saying it all of a sudden makes it an "extreme overreaction"? [Steven D'Aprano]
What are you talking about? I explained exactly what I meant: I think there are better ways that anonymous functions could have been
Notice: I never said "real, significant, non-trivial harm" anywhere in this entire discussion. I never said anything close to that. Stop jamming bullshit in my mouth to suit your narrative that I'm "extremely overreacting". It's not cute. [Steven D'Aprano]
This is a genuine question. I'm trying to understand your comments, not just dismiss them.
If you're so genuinely interested, then how come you couldn't be bothered to read my explaination above? [Steven D'Aprano]
Presumably you fear the same thing will happen again if we choose "partial" (otherwise, why raise the issue?).
There is no issue. I've already conceded that. Please read the conversation that followed with Neil Girdhar. I was simply stating a preference and trying to articulate my reasoning behind that preference. My whole intent was to +1 your alternative and say "I prefer given to partial". That's it. [Steven D'Aprano]
Python does have a long-standing tradition of sticking to mostly English words, a tradition for which I personally am grateful.
I am too. I'd like that to continue. [Steven D'Aprano]
Rude? Who would it be rude to if we had chosen "anonfunc" instead of "lambda"? [Steven D'Aprano]
How can we insist that 3/4 of the world learn English words to use Python
Do you really think that 3/4 of the world learns English just to write Python? Do you think the only english they learn are the built-ins and standard library of Python? English is a dominant language in business and programming. That statement is no more "privileged" than the statement that the US Dollar is the most popular global reserve currency. It's a fact that I have no control over. [Steven D'Aprano]
...if we aren't even willing to move out of our own comfort zone to the extent of learning accurate jargon terms from our own profession?
Very few of us are computer scientists by profession. That's not even where 'lambda' comes from. In computer science, it's called an "anonymous function". "lambda" comes from lambda calculus. [Steven D'Aprano]
I gave my reasons: it's shorter and less jargon while remaining fairly clear (in my opinion) You've already claimed that "possibly a less jargon name would be nicer", so I don't see the fuss. Apparently it's extreme when I say it. On Sun, Aug 12, 2018 at 8:06 PM, Steven D'Aprano <steve@pearwood.info> wrote:

He is questioning the concept that the lambda keyword has caused any harm. You assert that it caused minor harm. Minor harm can still be real, significant, and non-trivial. Has the keyword choice done any harm aside from mailing list jamming, and forum posts. I believe he is asserting that it hasn't. The burden of proof would be on you that it has caused any level of harm to the language of community, the criteria being that the harm be real, significant (if minor) and non-trivial. You will find no evidence to support your argument. You might find evidence that functional programming techniques are less useful with anonymous functions in python due to the restriction to only use expressions, but that isn't what is being argued.

On Mon, Aug 13, 2018 at 1:31 PM, Abe Dillon <abedillon@gmail.com> wrote:
If your reaction was extreme, saying so isn't attacking you.
Explain, please, what the HARM is that comes from the use of the word "lambda". In contrast, using the word "function" does definitely have harm, because you can no longer use the name "function" as a variable or parameter. Also, the signature is most decidedly NOT obvious from context, nor is it insignificant. Putting it first gives context to the body of the function. Python made the correct choice here.
No, but it's no less jargonny.
https://en.wikipedia.org/wiki/Anonymous_function "In computer programming, an anonymous function (function literal, lambda abstraction, or lambda expression) is a function definition that is not bound to an identifier." So... I would say "lambda" is very firmly connected with anonymous functions. ChrisA

[Alex Walters]
What, exactly, is the difference between "minor" and "non-trivial" and when did I say the harm was "significant and non-trivial"? [Alex Walters]
You will find no evidence to support your argument.
You could read what I wrote to Neil Girdhar who was able to engage with me without implying that I've lost my mind. [Chris Angelico]
If your reaction was extreme, saying so isn't attacking you.
Is this a hypothetical now? I said "*I think* they would (or do in the case of 'lambda') harm Python." I wasn't aware the word "harm" was something only deranged maniacs use. [Chris Angelico]
Explain, please, what the HARM is that comes from the use of the word "lambda".
I HAVE. [Chris Angelico]
Also, the signature is most decidedly NOT obvious from context
Who decided this? It's been decided by some committee? When you write a key function, you don't know how many arguments are going to be passed? [Chris Angelico]
nor is it insignificant.
I never said it was. I just said that the logic is more important from the standpoint of the reader. [Chris Angelico]
Putting it first gives context to the body of the function. Python made the correct choice here.
I disagree. This forum is looking more and more toxic. I've explained myself over and over again. I just wanted to +1 Steven's original comment. This is ridiculous. I guess I've pissed of the good-old-boys by calling out Steven's unnecessary condescension. Great. It looks like Python is in fantastic hands. On Sun, Aug 12, 2018 at 10:50 PM, Chris Angelico <rosuav@gmail.com> wrote:

On Mon, Aug 13, 2018 at 2:56 PM, Abe Dillon <abedillon@gmail.com> wrote:
lst.onselect = anonfunc(print(target_item)) What's target_item? If you can't see the signature and see that it's a parameter, you should look externally for it. What are the parameters to an onselect function? Doesn't that seem important enough to see the signature up front? It's not just *how many* arguments are being passed. It's what they're called, too. You cannot interpret the body of a function without knowing that. Hiding that off to the end would make the language worse, not better. Plus, can you name any similar language that does that? Every other language I can think of has the parameters before the body. While this isn't a clinching argument by any means (Python has a different argument order for the ternary if operator, for instance), it's indicative. ChrisA

[Chris Angelico]
If you're not even going to read the explanation I've already given, then I have no reason to respond. Your example looks nothing like what I've suggested and this whole conversation is being derailed by your need to win the argument. On Mon, Aug 13, 2018 at 12:04 AM, Chris Angelico <rosuav@gmail.com> wrote:

Now that the discussion has officially devolved into something that has absolutely nothing to do with the original topic, I'd like to point out something: (Note that I have no affiliation with the managers of this mailing list at all and am just posting this as an outsider.) In Steven D'Aprano's original message, I didn't see anything there as being a personal attack or as having an angry tone, at least based on his normal posting style. Maybe a bit critical and stern, but not really personal. You may have interpreted it as that, but I seriously doubt it was the intention. I'd like to propose an alternative to Hanlon's razor, the Internet razor: Never attribute to malice that which is adequately explained by lack of context in online conversations. Online, there is no tone of voice, facial expressions, or extra context to really help distinguish intent. Misinterpreting has been a classic issue that's been around for ages and has only gotten worse. When writing a message, we're responsible for ensuring that the intent is clearly portrayed. When reading a message, we're responsible for correctly interpreting such intent, and everyone is usually better off if, when in doubt, the interpretation leans towards ambiguity over malice. On Sun, Aug 12, 2018, 11:57 PM Abe Dillon <abedillon@gmail.com> wrote:
-- Ryan (ライアン) Yoko Shimomura, ryo (supercell/EGOIST), Hiroyuki Sawano >> everyone else https://refi64.com/

it becomes "toxic" only after off-topic. fine list needs just a reminder from time to time ! Abdur-Rahmaan Janhangeer https://github.com/Abdur-rahmaanJ Mauritius

I don't really want to get involved in this, but I feel like everyone is piling up on Abe unfairly. On Mon, Aug 13, 2018 at 1:14 AM Ryan Gonzalez <rymg19@gmail.com> wrote:
When Abe wrote just this: "but I think they would (or do in the case of 'lambda') harm Python" — which is nothing but an opinion. We're all welcome to our opinions without having to prove them like lawyers. Steve replied this: "That's an extreme overreaction. Do you mean to imply that there are people who looked at Python, loved the language, but decided to use something else because they didn't like the choice of the keyword "lambda"? If not, in what way is Python harmed? Would it be faster if the keyword was "function", or use less memory, or more expressive?" To my perhaps tender Canadian ears, that is incredibly abrasive. Steve could have just explained why he felt differently without slamming Abe's opinion as "an extreme overreaction" and then diving into a set of rhetorical questions that assume an extreme reading of Abe's statement. Now, as you say, this is Steve's usual posting style. But new people don't know him. I also found him quite abrasive when I started posting here, but then I noticed that it's not personal and he treats everyone this way. There are some great posters here, and I like to read python-ideas because I learn so much from them: Nick, Antoine, Brett, and Nathaniel to name a few, but there are many more. I think it's important for newcomers to try to be respectful, but it's also important to treat newcomers with the same kindness you would treat a guest in your home. Best, Neil

On Sun, 12 Aug 2018 23:56:24 -0500 Abe Dillon <abedillon@gmail.com> wrote:
My experience is that this forum was toxic almost from the start, because it encourages people to engage into the kind of behaviour you are witnessing now (i.e. largely pointless and semi-agressive nit-picking which sometimes feels straight out of the well-known Argument Clinic sketch). Regards Antoine.

On Mon, 13 Aug 2018 at 11:30, Antoine Pitrou <solipsis@pitrou.net> wrote:
IMO, things have got worse over time. As a forum explicitly designed for discussing speculative ideas, the general tone has become less and less sympathetic towards people (particularly newcomers, which is especially unfortunate) expressing ideas which are, shall we say, less than perfectly thought through. I'm OK with gently pointing out to a poster that they will need to tighten up their arguments and assertions as the discussion progresses towards a concrete proposal, but that's not how things feel any more. In particular there seems to be an extremely aggressive dislike of anything that seems like "opinion" which can't be backed up with solid evidence. Certainly we don't expect proposals based purely on subjective opinion to make it through to implementation, but we shouldn't be holding the process of exploring ideas to such rigorous standards. Anyway, I won't say any more, as I don't really know how we could change things. And yes, a lot of the above is my view, and is subjective. Asking me to provide evidence and back up my assertions sort of proves my point, so please treat it as just that, my opinion, and take it or leave it on that basis. Paul

What I feel we lack are better tools for checking bad behavior and nudging people in the right direction, apart from having discussions like this. Temporarily locking threads that have become heated comes to mind. As do temporary bans for rowdy members. As does closing threads that have ceased to serve any good purpose. These things would have been pretty handy in several recent and heated discussions, including the PEP 505 one I participated in a couple of weeks ago. How much of this is possible on a mailing list? I don’t know. But I remember a year or two ago there was a proposal to move python-ideas to a different format, perhaps a Discourse forum or similar, which would provide some handy administration tools and other UX improvements. That discussion, ironically, was beset by some of the very animosity that better tooling would help control. (And I learned a bit about email etiquette and top-posting...) Maybe we need to revive that discussion? Overall, I don’t think we have a people problem on this list as much as we have an administration tooling problem.

normally at above 20+ posts it gets crazy Abdur-Rahmaan Janhangeer https://github.com/Abdur-rahmaanJ Mauritius

This is a half-baked thought, but perhaps a sub-reddit would facilitate better moderation and we'd get the bonus of threaded discussions and a side-bar for ediquite and other important info. I know Reddit has a mixed reputation, but some of the best moderated subs like /r/science and /r/neutralpolitics have fantastic discussions. We could open /r/pythonideas and see if it gains traction. We also have the skill set to write a pretty good moderation bot. On Mon, Aug 13, 2018, 12:11 PM Michael Selik <mike@selik.org> wrote:

some mods warnings or reminders might also help ! Abdur-Rahmaan Janhangeer https://github.com/Abdur-rahmaanJ Mauritius

Cleaning out the Ccs, presumably subscribed. Nicholas Chammas writes:
I would go further, and say that use of the word says more about those who used it than about the list.
I disagree. I think this is a scale problem: we have too many people posting, some of them new or infrequent, to prevent (1) people getting triggered by one word in an otherwise excellent post and going off in their replies, (2) intemperate rebuttals to the replies in (1), or (3) interminably long threads sustained by people who don't yet know when not to post. If (1) and (2) can be solved by moderation, then you pretty much have a toxic channel. The best solution to (3) is not channel-wide moderation, but killing/ muting the thread or specific posters in your MUA. If you're going to participate in channels as high-traffic as the Python lists, and still try to hold down a day job, this is one of the very few features where I'm willing to say "bite the damn bullet and get a REAL MUA!" It really improves life. If most people have muted the thread, there's little to no harm in letting those who still care continue. This also has the advantage that you don't have to wait for a thread to be of use to nobody to kill it. You can do that now!
PEP 505 was an example of none of the above as far as I can see, though. I think it's tough to find places where you could invoke a thread freeze or a poster ban and not get a storm of pushback. And it's kinda hard to see how killing a thread on an open PEP is useful.
How much of this is possible on a mailing list?
Poster bans, whether temporary or indefinite, are possible. Thread freezing or closing are in principle possible, but they'd be really annoying to posters due to the nature of email, I suspect (posts would bounce and clutter up your inbox later, rather than having the "post reply" function disabled in the UI). Nor are they implemented in GNU Mailman, although spam-checking could probably be coerced to serve (ban messages where In-Reply-To or References contains recent IDs in the frozen/closed thread). This would require some additional scripts for efficient admin, and MUA tooling to extract References would be nice, but all that doable in an afternoon or two.
Going back to that discussion now that Guido is less involved might get you a different answer. (He was not a fan of Discourse, and while he told me he likes Zulip at PyCon Cleveland, he also said he sees it as independent of the function of mailing lists. He also said Mailman 3's HyperKitty forum-like functionality sounds like it will be good enough for him soon enough, so he'd probably be opposed to moving to forum software on the "don't break what don't need fixing" principle. All that is almost moot now.)
Overall, I don’t think we have a people problem on this list as much as we have an administration tooling problem.
That's what @jack says, too. :-/ Sorry, that's a bit too snarky, but the fundamental problem is that *people* post too much. That's a *people* problem even though there are no problem people, and the people that are deciding what to post aren't the admins (unless you'll accept out-and-out censorship, or an editorial board if you prefer a euphemism). So I don't see an admin tooling solution here. Steve -- 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

Hi All Here's something that's at the core of my approach. Faced with this sort of problem, I read again https://www.python.org/psf/codeofconduct/. And then I compare my intentions, words and actions to the guidelines in this, the Python Community Code of Conduct. Only when I have, so to speak, regained my purpose and composure do I consider the conduct of others. At least, this is what I aspire to do. -- Jonathan

I'm perhaps the newest and most ignorant subscriber here - I daresay everyone here has superior python knowledge to me, and all my other computing knowledge is inferior to what I can do with python. (and so far, I've had no influence at all on python) However, this mailing list, generally, does not seem toxic to me at all. I haven't experienced any condescension about my lack of knowledge. While I can acknowledge that there might be superior alternatives to email, I do think the threshold of subscribing and listening in is lower than a lot of other options, like for example subreddits. I for example would have never come if it'd been one of those. 2018-08-14 10:53 GMT+02:00 Jonathan Fine <jfine2358@gmail.com>:

I never said or implied that you lost your mind. Only that you were wrong. It is possible to be wrong and sane. However if you really insist that the two are one in the same... you might actually need to seek out professional help.

On Sun, Aug 12, 2018 at 8:31 PM, Abe Dillon <abedillon@gmail.com> wrote:
Lambda calculus IS computer science. Rejecting lambda as CS is as bad as rejecting the + operator because that's mathematics. I can legitimately argue that + in Python is not the + in mathematics because the Python mathematical operators operate on integers and floats, not real numbers. Therefore we should use a different word like "floatadd". Of course not. Lambda calculus is a model of computation. It was invented about 30 years before the name "computer science" but is nonetheless foundational computer science. If using lambda as a keyword leads people to go and learn about lambda calculus that is a good thing. And as to saying a lambda function is an "anonymous function": the anonymity is not a property of the function. If I assign it to a name, it's no longer anonymous. Really a "lambda" or "lambda function" is just a function, but "lambda" is a synecdoche for "function created with a lambda expression". --- Bruce

On Tue, Aug 14, 2018 at 4:00 AM, Bruce Leban <bruce@leban.us> wrote:
True, but at that point, you get into hairy points of definitions. Which of these functions is anonymous? def do_stuff(callback): ... do_stuff(do_stuff) do_stuff(lambda: 42) do_stuff(callback=lambda: 42) Obviously do_stuff itself has a name. When you pass it a parameter, it can access that as "callback", which means the function has been assigned to a name. Does it cease to be anonymous? What if you use a keyword argument? Within Python, there's a fairly clear definition: if there is something in the source code which sets the function's __name__ attribute, it's not an anonymous function. So anonymous functions come from: * Lambda expressions, always called "<lambda>" * Comprehensions/genexps, always called "<listcomp>" etc * Callable objects that aren't functions (or classes, since those have names) * Maybe something else that I've forgotten. You're absolutely right that a "lambda function" isn't really a thing, in the same way that Python doesn't have "raw strings" (only "raw string literals", which are literals which result in perfectly ordinary strings). But the anonymity of them is a somewhat measurable feature, even if it isn't very important. The distinction between "lambda functions" and "def functions" is important to style guides, but otherwise shouldn't matter. ChrisA

[Bruce Leban]
Lambda calculus IS computer science.
It's a foundation of computer science. That doesn't mean it "IS" computer science. Set theory is a foundation of computer science. It's still it's own discipline. [Bruce Leban]
Rejecting lambda as CS is as bad as rejecting the + operator because that's mathematics.
This is a complete misunderstanding of my argument. Not all programmers are computer scientists. In fact, not all programmers are professional. Many, including myself, came from engineering. Many came from other scientific fields. Many came from finance and all sorts of fields. Many are teenagers who just want to build a cool website or a video game or scrape song lyrics for their favorite bands. The whole point of a programming language is to bridge the gap between machine code and natural language (in Python's case English, as with most other languages). It's to make reading and writing code easier through abstraction, not to create ivory towers through the use of esoteric jargon. It's not supposed to make a cool kids club for people privileged enough to study CS in college. At least that's not my goal. [Bruce Leban]
Yes. I know. [Bruce Leban]
If using lambda as a keyword leads people to go and learn about lambda calculus that is a good thing.
I don't think the point of Python is to force people to eat their vegetables. You might think it's a good thing if everyone learns about Turing machines and the Halting problem and Kolmogorov Complexity and X86 machine code, etc. but that's not what Python is for. I may think that everyone should learn what I learned in college about electromagnetics and semiconductor physics, etc. But I'm not arrogant enough to force that on people who just want to use abstract tools to get some job done. I didn't realize that my distaste for 'lambda' was such an unheard-of opinion. I could have sworn that the likes of Guido Van Rossum and Raymond Hetinger also found the term at least a little troublesome. As someone who has taught Python professionally, I can say that there is a strange mental block regarding lambda expressions. Pretty much every student I've had has struggled with lambda expressions, even those who grasp similarly complex constructs like decorators with ease. This includes students who learned english as a second language. I can only attribute that to the word 'lambda' being confusing as hell. [Bruce Leban]
And as to saying a lambda function is an "anonymous function": the anonymity is not a property of the function.
Yes, It is:
[Bruce Leban]
If I assign it to a name, it's no longer anonymous.
That's not how variable assignment works in Python. The name of the variable doesn't become an attribute of the object assigned to the variable. [Bruce Leban]
My whole point was to be less pedantic, not more pedantic. Pragmatism should prevail over pedantry. This is why, as I've stated earlier, I know that lambda expressions aren't going to change any time soon and I'm fine with that. I consider it a bit of a wart, but whatever. I'm getting really tired of having to defend this opinion. Also, this argument makes no sense. Just because there isn't a way to represent all real numbers in a computer, doesn't mean that integer, floating point, and fractional addition become different kinds of addition. On Mon, Aug 13, 2018 at 1:09 PM, Chris Angelico <rosuav@gmail.com> wrote:

On Tue, Aug 14, 2018 at 5:08 AM, Abe Dillon <abedillon@gmail.com> wrote:
The whole point of a car is to make driving easier through abstracting away the internal details of petrochemical propulsion, but if someone says "I don't want to know about 'gears' or 'brakes' or any of these technical terms", you wouldn't want them driving on the roads you're on. There is a certain level of comprehension that you can't avoid. (If you don't know anything about how to use a car, you can still ride in one, but you can't drive it; and you don't need to understand about anonymous functions in order to operate a computer, but you'll need them to program effectively.)
As someone who currently teaches both Python AND JavaScript professionally, I can say that there is a strange mental block regarding anonymous functions, and it's nothing to do with the word "lambda". In JavaScript, anonymous functions are created with the word "function" (same word as is used for declared functions), and there are just as many points of confusion as there are with Python. ChrisA

[Chris Angelico]
This was originally in response to Bruce Leban's assertion: "If using lambda as a keyword leads people to go and learn about lambda calculus that is a good thing." Are you saying that knowing "what lambda calculus is" is as important to programming in Python as knowing "what breaks are" is to driving? If so, I don't think that analogy holds water. I don't think lambda calculus is fundamental to knowing how to write a program. I don't even think anonymous functions are fundamental to writing a program. I think a programmer could go their whole life without ever knowing what a lambda expression is and still manage to write plenty of very useful code. It seems to me like the whole point of this discussion has turned into getting me to repent and profess my undying love for lambda expressions. I'm sorry to disappoint. Maybe we should split off this discussion into a thread where people can keep badgering me to come up with an objective proof that Python's lambda expressions are not the best implementation possible. Then, at least, we can stop polluting this thread with this tangent. It doesn't seem to matter how many times I try to point this out, but my original comment should be read as: "I like Steven's idea. I prefer `given` to `partial`." I'm sorry I even brought up lambda. I'm truly sorry to all those who wanted to seriously discuss alternatives to functools.partial. On Mon, Aug 13, 2018 at 2:17 PM, Chris Angelico <rosuav@gmail.com> wrote:

On Tue, Aug 14, 2018 at 6:26 AM, Abe Dillon <abedillon@gmail.com> wrote:
No, lambda calculus isn't on par with brakes - but anonymous functions are, and if they're called "lambda", you just learn that. In fact, I would say that the word "lambda" is the least troublesome part of anonymous functions, callbacks, and related topics. It's the same with "partial". Actually, I didn't think of that as "partial application" but as "partial specification of parameters". If you can grok the concept that you can take a function, lock some of its parameters, and get back another function, then you should be able to learn a word to associate with it. ChrisA

Chris Angelico wrote:
No, lambda calculus isn't on par with brakes - but anonymous functions are, and if they're called "lambda", you just learn that.
It's like saying that people would find it easier to learn to drive if "brakes" were called "stoppers" or something. I don't think that's true. -- Greg

On Mon, Aug 13, 2018, 5:48 PM Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
There isn't much jargon involved in learning to drive and most of it is natural: left turn, right turn, blinkers, etc. Compare this with learning to sail. I still don't remember which side is starboard.

On 2018-08-14 02:46, Michael Selik wrote:
<OT> "Starboard" is the side on which was the "steerboard", the large "board" or oar used for steering the boat, a predecessor of the rudder. Most people are right-handed, so it was put on the right-hand side of the boat. Given that, it made sense to tie the boat up to a jetty on its unobstructed left-hand side, the "port" side. Starboard = right, port = left. </OT>

Pedantically, Python's lambda isn't even the same thing as in the lambda calculus. The mathematical abstraction is always curried, and neither Python nor most languages that use the spelling 'lambda' do that. So even assuming users must learn technical vocabulary, this is an inaccurate such term. 'def' or 'func' would be less deceptive here for anonymous functions. The burden of learning the word lambda—and unlearning it's meaning in mathematical logic if you happened to have used that—it's not huge. But it's more than zero. And probably more than leaning 'function'. On Mon, Aug 13, 2018, 8:49 PM Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:

On Tue, Aug 14, 2018 at 7:58 AM, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
Reminds me of this: "So, there's some buttons on the floor. Pedals. Uhh.... That's the "go" pedal... That, I believe, is the stopper... and this... this doesn't do anything...." -- Wreck It Ralph, trying to figure a car out. I'm pretty certain he didn't do any better that way than if he'd used words like "accelerator" and "brake". In fact, this supports my assertion that it's not the terminology that bites you - it's the concepts behind it. Even if he'd known that the other pedal was called the "clutch", it wouldn't have helped him much without knowing how to use it... Whether you spell it "function(arg) {...}" or "lambda arg: ...", it's the semantics that are hardest to learn. ChrisA

The conversation about syntactic sugar for ``functools.partial`` led to a question about whether jargon like "lambda" makes the concept of an anonymous function more difficult to learn. In my own experience teaching, I find that many concepts are easier to introduce if I avoid the Python jargon until after I've explained what it does. This is supported by education research. Some light Googling found a study on the topic [0] that is consistent with my own observations. Picking good names is hard [1]. It's tempting to use terms based on the origin of the concept, historical odds and ends, or even jokes. This can help someone remember the concept when someone is familiar with the origin, history, or joke, but makes the concept more confusing and hard to remember for others. I recommend trying to buck tradition and pick terms that are as simple as possible, requiring the least context to make sense. Jargon can be useful for allowing an expert to quickly identify the context of a term [2]. Plain language phrases can easily create namespace collisions. However, someone searching for or reading about Python concepts already knows that the context is Python programming. Good comparisons can be found in other fields: * Driving -- brakes vs stoppers * Sailing -- starboard vs right-side * Medicine -- postprandial vs after-meal * Biology -- dinosaur vs direlizard In the last case, it turns out direbird might have been a better term. I'm not sure if that supports or detracts from my argument. [0] https://iubmb.onlinelibrary.wiley.com/doi/full/10.1002/bmb.20922 [1] https://martinfowler.com/bliki/TwoHardThings.html [2] https://www.nngroup.com/articles/specialized-words-specialized-audience/ On Mon, Aug 13, 2018 at 9:00 PM Chris Angelico <rosuav@gmail.com> wrote:

On 14/08/2018 20:42, Michael Selik wrote:
While NOT wanting to start another fight I feel that I must put my pedant hat on & point out that the above highlights why domain specific words are used and their specificity actually highlights important concepts, i.e.: * Brakes are used to apply breaking, (i.e. to slow the vehicle, possibly to a stop), while stoppers STOP something. * Starboard = to the right when facing the bow (front of the vessel) not "my right", "your right" or "their right" (which depends on which way you, I & they are facing). * postprandial = after Lunch (not after eating any meal or after a snack). * A dinosaur is specifically an extinct terrible (formerly considered) lizard where as a Gila Monster is definitely a scary & dangerous (dire) lizard. In all of these cases there is a specificity to the word used that is missing from the alternative offered that will, hopefully, be raised by the use of that word. Unfortunately many people, when trying to explain what the word means fail to highlight where it is different (the number of times that I have heard people "explain" port and starboard as left and right without mentioning the word bow or forward is countless). Using a slightly unfamiliar word can cause people to ask, or think about, why this is different & what the difference is while also drawing a parallel that can help the user/student to understand & remember the concept. Also, picking a label for something, and using it consistently, can vastly simplify things like manual searches (or on-line searches). The English language has, historically, always borrowed, co-opted and sometimes perverted words from other languages to allow distinct concepts to be expressed concisely - which I personally, (admittedly as a native speaker), find rather useful. -- Steve (Gadget) Barnes Any opinions in this message are my personal opinions and do not reflect those of my employer. --- This email has been checked for viruses by AVG. https://www.avg.com

Steve Barnes wrote:
* Brakes are used to apply breaking,
I hope they actually apply braking, not breaking. :-)
* A dinosaur is specifically an extinct terrible (formerly considered) lizard
Which technically is not a lizard. -- Greg

Steve Barnes and Greg Ewing wrote:
I can't resist. Puffinus puffinus is the scientific name for (drum roll) no, not the Atlantic (or common) Puffin but (off-pitch fanfare) https://en.wikipedia.org/wiki/Manx_shearwater -- Jonathan

On 15/08/18 06:21, Steve Barnes wrote:
I think you and Michael are arguing to the same end. He was suggesting that it's easier to teach a concept by introducing the idea and then a name for it, rather like the way Python creates objects before binding them. -- Rhodri James *-* Kynesim Ltd

[Michael Selik]
To clarify: The original statement by Steven D'Aprano, "although possibly a less jargon name would be nicer..." indicated to me that he thought there might be situations where less jargon terms are preferable to jargon terms. The argument I tried to make is, "yes I believe there are cases where a less jargon identifier is preferable and that I believe 'lambda' is an example of a missed opportunity to use a less jargon (maybe 'esoteric' is a better word here?), more descriptive name." Subjectively, I don't like lambda expressions. I find the word 'lambda' to be an eye-sore in an otherwise very elegant language. That being said: I believe subjective valuations are rarely devoid of subtle, underlying motivators that are at least grounded in logic if not objective. It's just hard to put your finger on it most of the time. I often try to root out those motivators for why I feel the way I do and articulate them as best I can. At the end of the day, though; I can't always provide a completely objective, logical proof for why I feel the way I do. For instance: when the iPhone was introduced, a lot of people praised it's subjectively "slick" user interface. I believe that perception of slickness is partly because the iPhone emulated physical interfaces very well so it leveraged people's intuition about the physical world. It was delightfully intuitive. I believe that part of my distaste for lambda is that it's an esoteric word that doesn't convey any meaning to someone who's never heard of a 'lambda expression' (which was the case for me when I first encountered it). Even after I had heard of a lambda expression, the fact that the word had little other connection to anything relevant in my brain meant that I had to mentally translate it every time I read for a couple of years. [Steven Barnes]
I don't think this is comparable to calling a car's brakes, "stoppers" for several reasons. 1) What we call something usually relates to how humans communicate to other humans about that thing, not how we actually use the tool. I'm not against the idea of jargon. It clearly serves a useful purpose for humans to communicate to other humans both concisely and with precision. When I tell someone at work that a service went down and they say, "I'll take a look at the logs", I know they're not talking about lengths of cut or fallen tree. I'm glad humans are so good at deducing context that we don't have to constantly disambiguate everything. I also understand that this practice of overloading words sometimes leads to strange results like "currying". Maybe calling it "signature reduction" would have been too unwieldy and/or caused confusion with the word "reduce" which is often used in the same context. None of that has to do with how I interact with a car. Few brake pedals say "brake" on them. I don't have to use the word "brake" to slow down my car. Few of the interfaces in my car even have words. There's no lever that says "high beams". There's no dashboard indicator that says "high beams". I don't have to use the phrase "high beams" to turn on my high beams. At the same time, I don't need to use or know the word "ternary" to read or write a ternary expression in Python. I don't think that was a mistake or a missed opportunity to force people to look up the word "ternary". Sometimes in highly specific contexts, we deal with nuanced concepts like the difference between a parameter and an argument. So we use jargon to distinguish between them. That's not as much of problem in a programming language. The constructs in Python have to have an exact meaning by default. Clearly defining and separating name-spaces is an inescapable fact of life in programming. There's no chance of Python accidentally misinterpreting which "log" you're talking about. There's no potential for a "who's on first" gag <https://www.youtube.com/watch?v=kTcRRaXV-fg>. 2) Cars tend to actually use pretty sensible naming schemes. A windshield shields you from the wind. A windshield wiper wipes the windshield. Windshield wiper fluid is fluid that helps the windshield wiper wipe the windshield, etc. If they called windshield wiper solution "epsilon", it wouldn't cause more crashes or anything, it would just be more confusing than it needs to be. 3) It's not like calling 'brakes' 'stoppers'. It's more like calling an expression that makes a function by some random greek letter. I don't see much need for a metaphor. [Steven Barnes]
* postprandial = after Lunch (not after eating any meal or after a snack).
Not according to Google <https://www.google.com/search?q=postprandial+definition>, Merriam-Webster <https://www.merriam-webster.com/dictionary/postprandial>, Oxford <https://en.oxforddictionaries.com/definition/postprandial>, or Wikipedia <https://en.wikipedia.org/wiki/Prandial>. [Steven Barnes]
I understand the potential benefit of jargon as stated above, but even this isn't always true. Sometimes jargon is created that is counterintuitive and then it just sticks because changing it would be a huge hassle. In electrical engineering, current is supposed to be the "flow of positive charge", but charge conventions were established before we knew how atoms work and learned that positively charged particles don't often move in circuits. Dinosaurs are another good example. Sometimes jargon is a mistake. [Steven Barnes]
It depends on if it's easy to tie said word into a broader understanding. It's easy for me to remember that "agua" means "water" in Spanish because it's very similar to a words that relate to water in english like "aquifer". I have trouble remembering that "izquierda" means "left" because I don't know any word like it. I have to pause and think about it every time without fail! Similarly, I can guess that "anonymous function" means a function without a name, but it took me a while to get used to "lambda" because it was just dangling there with no other connection to its context. Even when I learned about lambda calculus it didn't help much because the "lambda" was an arbitrary choice. There wasn't any way for me to tie it into a richer context. [Steven Barnes]
Also, picking a label for something, and using it consistently, can vastly simplify things like manual searches (or on-line searches).
Yes, Steven D'Aprano mentioned this and it's a fair point. I think it'd have to be pretty horrendous jargon to justify "create [an] association from scratch" as Steven put it. I've since gone back on my original push for "partial" over "given" because I don't think it meets that criteria. I think that "lambda" is a different case because there already existed several better alternatives in other languages and, in the case of "def", in Python itself. [Chris Angelico]
Whether you spell it "function(arg) {...}" or "lambda arg: ...", it's the semantics that are hardest to learn.
Naming and semantics are essentially orthogonal. Sure callbacks and the like can require some painful mental gymnastics, but that's independent of choosing "function" or "lambda". When I talk about students having more trouble learning lambdas than I expect, I'm specifically talking about lambdas, as in:
func = lambda x: x*x
Even students that seemed to quickly grasp functions as first-class objects would stumble on basic lambda expressions. Not as much trouble as callbacks and other, more complex concepts, but more trouble than regular function definition. Anyway, the question should be "Is it always best to use jargon in the implementation of Python features? If so, how do you figure? If not, when and why should it be avoided?" On Wed, Aug 15, 2018 at 12:21 AM, Steve Barnes <gadgetsteve@live.co.uk> wrote:

learn better how to find a compromise (strike a balance) between
Summary: Discussion of the words 'jargon' and 'chatter'. Recommend that we precision and simplicity. This thread is, in part, about the meaning, use and usefulness of words. And 'jargon' is what we are talking about. What is the meaning and use of 'jargon'? According to https://www.etymonline.com/word/jargon (discovered https://en.wikipedia.org/wiki/Jargon) === jargon (n.) mid-14c., "unintelligible talk, gibberish; chattering, jabbering," from Old French jargon "a chattering" (of birds), also "language, speech," especially "idle talk; thieves' Latin" (12c.). Ultimately of echoic origin (compare Latin garrire "to chatter").
And according to https://www.etymonline.com/word/chatter === chatter (v.) early 13c., chateren "to twitter, make quick, shrill sounds" (of birds), "to gossip, talk idly or thoughtlessly" (of persons), earlier cheateren, chiteren, of echoic origin. Compare Dutch koeteren "jabber," Danish kvidre "twitter, chirp." Of teeth, "make a rattling noise from cold or fright," mid-15c. === Ordinary words can acquire a specialised technical meaning. For example === https://en.wikipedia.org/wiki/Machining_vibrations Machining vibrations, also called chatter, correspond to the relative movement between the workpiece and the cutting tool. The vibrations result in waves on the machined surface. This affects typical machining processes, such as turning, milling and drilling, and atypical machining processes, such as grinding. === Sometimes, machining vibrations make a ch-ch-ch-ch chattering sound. My opinions are that the correct technical phrase is 'machining vibrations', which is good for learned articles. But 'chatter' is better in the workshop. As in 'lubricate the drill bit to reduce chatter'. And here's another example === https://en.wikipedia.org/wiki/Chatter_(signals_intelligence) Chatter is a signals intelligence term, referring to the volume (quantity) of intercepted communications. Intelligence officials, not having better metrics, monitor the volume of communication, to or from suspected parties such as terrorists or spies, to determine whether there is cause for alarm. === Back to 'jargon'. === https://en.wikipedia.org/wiki/Jargon Accessibility issues With the rise of the self-advocacy movement within the disability movement, jargonised language has been much objected to by advocates and self-advocates. Jargon is largely present in every day language, in newspapers, government documents, and official forms. Several advocacy organisations work on influencing public agents to offer accessible information in different formats. [...] There is a balance to be struck, as excessive removal of technical terminology from a document leads to an equally undesirable outcome—dumbing down. === I think this last quote gets to the heart of the matter we're discussing. I suggest we learn better how to find a compromise (strike a balance) between precision and simplicity. -- Jonathan

tl;dr I don't think so, not very much. There are bigger fish to fry. I would appreciate comments on the last paragraph (before the footnotes), which can be read standalone. If opinion is at all favorable, I'll raise it with the PSF. Jonathan Fine writes:
I'm not a big fan of asking that everybody put such effort into documentation for code they're developing. IMHO, where available users should just buy books by professional writers written to their level, rather than imposing this burden on the software development project. Developers themselves should be asked to write concise, precise documentation. I don't think it's at all a good idea to burden them with "accessibility" issues. It's hard enough to write good notes for yourself a year hence! Tutorial writers, OK, they should be cautioned to avoid jargon, but if they aren't already judicious about using jargon, maybe they shouldn't be writing tutorials at all? What about documentation patches from users (including developers who didn't write the docs being edited)? In general, I favor restricting these to correcting bugs, missing information, and extremely convoluted syntax. If the docs use jargon (by which I mean "informal technical terms, often local to the project") which is intelligible to long-time users but may be off-putting to newcomers and infrequent users (of the documentation, not the software!), I think it is better to provide a glossary.[1] The problem with editing inline is that there are direct costs and a missed opportunity. The direct costs include the potential for introducing imprecision and outright documentation bugs, and code churn (increasing the cost of reading diffs). The missed opportunity is that a good glossary will also serve users who graduate to "informal write-only documentation" including archives of mailing lists and group chats, and the issue tracker. I'm not sure about the "conventional" accessibility issues (ie, excluding newcomers, non-native speakers, and translators). As a developer/maintainer I have had a small amount of contact with users with perceptual and motor disabilities, but have never heard them complain[2] about jargon. (Small sample, but before we presume they would benefit from simplified docs, we should consult experts.) Serving non-native-speakers is a tough call. On the one hand, they would be best served by good translations and glossaries of English jargon in their native language. You don't need to speak English at all to write good programs in programming languages based on English keywords, and the concepts are easier to understand, and precision easier to obtain, if you're not fighting with a second language. For many of my students, the first language is Chinese, the second Japanese, and the third English. English keywords and the occasional concept denoted by jargon don't faze them. The problem is more following simple directions about inserting punctuation, misspelled words, and so on -- the closest literal translations often are poor semantic matches, and so all English is awkward for them. But I can understand half (well, 10% ;-) of what their sempai are saying in Chinese, because of the keywords and borrowed jargon -- and so can the kohai. Jargon isn't a problem; it's just another symbol for an unfamiliar concept that they need to learn. On the other, we're not doing a good job of encouraging translators. There are a lot of volunteers in the translation community, and (like programmers) an important reward is getting their product into the distribution. (This is *not* a complaint about the Python maintainers. The costs of infrastructure and maintaining synchronization of translations with the original documentation are still quite high.) I suppose there must be corporations who are doing translations for their Python-based products, and we can do a better job of getting them to contribute them upstream (although we currently have the problem of "where is upstream?" since we don't distribute translations ourselves). Finally, before getting the project into the hairy maintenance issues that go with distributing translations, I suggest the PSF could buy the high-quality tutorial books and textbooks (and maybe dictionaries as well) for translators. Very cheap, but the symbolism that "somebody noticed, and they care!" is a big reward for many contributors. Another possibility would be complimentary tickets (and/or travel grants) to PyCon. From past experience I gather that many translators are more focused on their natural language than on the projects whose documentation they translate, so it's probably not worth sending them to big international PyCons to be lionized by the core developers and PSF board members. On the other hand going to a local PyCon might be attractive, especially if they got complimentary tickets to some of the parties, where they would be introduced to keynote speakers and the like, and would be lionized by the people they're writing for. Not to mention getting feedback. Steve Footnotes: [1] The convention in academic and textbook writing of providing definitions (and expansions of abbreviations and acronyms) at first use is a good one, but the glossary is essential in technical documentation because users frequently dip into the middle of a document for a specific entry rather than reading linearly. [2] In fact, users with disabilities rarely complain in my experience. They just point out their issues without attitude.

Hi Stephen Thank you for your message. I'll respond just to a few of your comments. HOW MUCH EFFORT ON DOCS ========================== Myself and you wrote:
Sections 6 and 7 (out of 31) in devguide for the Python project are on this. === https://devguide.python.org/docquality/ https://devguide.python.org/documenting/ === This is about 6.5%, of the devguide, by section count. There are at present 108 open documentation issues (out of about 6,000). This is about 2%. I'm proposing for example that we review, and if possible improve, these two sections in the devguide. This review would be evidence based. Not everyone need be involved in this. I suggest that doing this now would, over 3 years, significantly improve our Python documentation. AN EXAMPLE - super() ================== By chance, I wanted today to read about and then use super(). I found === https://docs.python.org/3/library/functions.html#super For practical suggestions on how to design cooperative classes using super(), see guide to using super(). === To my surprise, I found that this links, not to another part of the docs, but to === https://rhettinger.wordpress.com/2011/05/26/super-considered-super/ === This excellent blog post is not, of course, indexed for the docs search. THE GLOSSARY ============= You wrote:
Five days ago, I raised an issue (one of the 108 open issues), to improve search in the glossary. And thanks to Ammar Askar, there's already a patch and pull request. This delights me. https://bugs.python.org/issue34398 https://github.com/python/cpython/pull/8773 TRANSLATION ============ You wrote:
There's already prior art on this. See: PEP 545 -- Python Documentation Translations https://www.python.org/dev/peps/pep-0545/ One of the alternatives in PEP 545 is === Simplified English It would be possible to introduce a "simplified English" version like wikipedia did, as discussed on python-dev, targeting English learners and children. === I think this would be a good idea, particularly for the tutorial (and other beginner materials, such as the glossary). -- with best regards Jonathan

Hi Stephen I've just been reading the (excellent) discussion, started by Victor Stinner [Python-Dev] Translated Python documentation https://mail.python.org/pipermail/python-dev/2017-February/147416.html # Start of thread. You wrote, and asked for comments on:
I very much more prefer Victor's suggestion (I give the whole message): === https://mail.python.org/pipermail/python-dev/2017-February/147485.html IHMO translating the *whole* Python documentation at once by a professional translator can be very expensive, no somthing that the PSF would affort. Which language would you pick? Depending on what? We already have motivated translators for free who only ask us for the permission to make tiny changes to make their life simpler and make the doc more visible. I'm in favor of allowing them to translate and make the translated doc official ;-) IMHO a better usage of the PSF funding would be to organize some local sprints to translate the Python documentation. Such sprints are fun, cheap, and can be a nice opportunity to recruit free and motivated translators. We are looking for people involved to translate the doc the doc is updated, not only translate the doc once and go away. Right? === -- Jonathan

Jonathan Fine writes:
I think we can do both. My suggestion is very cheap, and requires no change to release management, or even action by release managers and committers: the PSF board could announce the policy tomorrow and start cutting checks next Monday, and python-dev wouldn't notice. (I'm not suggesting overnight rollout is a good idea, and practically speaking the board can't act that fast, of course. The point is that there's potential encouragement for translators, improved documentation for users, at zero cost to the code developers and release managers.) The suggestion of providing official translations in the distribution has been made before, and resisted by the maintainers and committers. I don't oppose the idea myself, I simply observe that resistance and the explanations offered, and assume there is good reason for it. Steve

o/
IMHO a better usage of the PSF funding would be to organize some local sprints to translate the Python documentation.
That's what we're already doing here in France for the french translation, and the PSF is already fouding them (thanks!) in Paris [1] and the AFPy [2] is founding them in Lyon. [1]: https://www.meetup.com/fr-FR/Python-AFPY-Paris [2]: https://www.afpy.org/ -- Julien Palard https://mdk.fr

On 18/08/18 01:59, Abe Dillon wrote:
While I don't entirely disagree with you, if I had been responsible for inventing that bit of Python I would probably have gone with "lambda" too. It had been part of my vocabulary as a computer scientist long before I met it in a programming language. Whether it's a *good* choice or not... possibly reusing "def" would fit people's expectations better, or perhaps it would have caused more confusion. Who can tell? Jargon becomes jargon because it's useful to enough people, for occasionally rather odd definitions of "useful". In the case of lambda, it's shorter than "inline function definition" and lambda calculus at least shows up on most CompSci courses. Once it settles into a group, you use it because other members of the group will understand what you mean and might not understand if you rephrase it.
One of the things Apple have always been very good at is thinking hard about user interfaces. What made the iPhone so good was that they emulated the right physical interfaces, so flipping a page when you're reading rather than pressing a button. -- Rhodri James *-* Kynesim Ltd

Responding out of order. [Rhodri James]
Yes, that's exactly what I was trying to say. An important point that I think keeps getting lost in this conversation is that Python's grammar, syntax, and standard lib are it's user interface. There are very different constraints on Python's UI than there are when humans have to communicate directly with other humans. I have no problem using words like "closure" or "lambda expression" or "ternary expression" when communicating with other humans about programming language features, but jargon doesn't often make sense as part of Python's UI itself. Again, we don't use the word "ternary" in Python's ternary expressions. [Rhodri James]
Yes, again: I understand the utility of jargon. I don't think "anonymous function" would be an improvement over "lambda" because, while it is fairly descriptive, it sacrifices too much brevity. However; the word "anonymous" is redundant. You can tell the function is anonymous by virtue of the fact that it doesn't have a name. "function" is only two characters longer than "lambda" and is actually descriptive, but it probably would have caused backwards compatibility issues (same with "func" or "fun"). "def" would have been even shorter than "lambda". [Rhodri James]
and lambda calculus at least shows up on most CompSci courses.
I suppose if by "courses" you mean "course plans", I highly doubt that the majority of CS classes cover lambda calc, though; I couldn't say for sure because I, like many programmers, didn't take CS in college. There are many disciplines that get by on basic algorithms, data-structures, and a pinch of theory. [Rhodri James]
If the group you're referring to are Computer Scientists, then I don't see why they would be confused by a syntax that omits the word "lambda" since very few languages use the word "lambda" to denote a lambda expression. [Rhodri James]
I don't see how "def" could cause more confusion than "lambda". Those who don't know what "lambda" refers to would at least have some notion of what "def" means, and those who have studied and know what lambda calculus is should also have very little trouble. I don't expect it would confuse someone well versed in computer science any more than a check-engine light would throw off an expert mechanic. They can at least google "python anonymous function" or "python lambda expression" and get results that tell you how to write a lambda expression in Python.

Rhodri James writes:
I was an economist then, and I'm an economist still, but I met lambda in 1977. Surely lambda has had that role in computer languages since shortly before I was born. I would guess anybody above a certain age would reach for "lambda" first for a keyword to denote or define an anonymous function. Not because of the lambda calculus, but because of Lisp. (OK, that's indirectly because of the lambda calculus.) Had Guido decided to change it to "def", I suspect he'd be regretting it slightly today, for reasons similar to the regrets about "range": we normally only allow omitting positional arguments at the end of the list. Maybe there's a better word than "regret". After all, It's hard to see how you could prototype range better than "range([START,] END, [STRIDE])", and the same might be true for "def [NAME] ([ARG0,] ...):".

On Tue, Aug 21, 2018 at 02:07:33PM +0900, Stephen J. Turnbull wrote:
Its pretty much a term of art. (Aside: "term of art" is itself a term of art: https://legal-dictionary.thefreedictionary.com/Term+of+Art ) I think that complaining about lambda is like complaining about "3-sigma versus 6-sigma processes" in process management. (Not computer processes, manufacturing processes and quality control.) Or for that matter, "mean" and "standard deviation" in statistics. The main difference is that most people are introduced to mean and stdev in secondary school, while functional programming idioms and lambda are generally stumbled across in the field. (I know that's how I learned of the term: through Python.)
Secure in the knowledge that Guido probably isn't reading this and won't contradict me *wink* I'm going to try channelling him. I think he would regret "def expressions", but not because of the range reason. I think its because he likes the relatively strict demarcation between statements and expressions. We have 4 statements that have a expression form: if...else versus ternary if expressions; for loops versus comprehensions; (soon) = assignment versus := assignment expressions; and def versus lambda. (Did I miss any? I don't include technicalities like dot attribute access versus getattr and similar.) It's notable that in none of those cases the syntax is quite the same in the two forms. There's always enough differentiation between the statement and expression that there's never any ambiguity which is intended. We don't have: result = if condition expression else expression where it is the lack of colons which hints that it is an expression, we have a completely different syntax. So I think Guido probably wouldn't like the idea of using def in expressions: def function(arg, callback=def: None): pass That's my guess, for what it's worth. -- Steve

[Stephen Turnbull]
According to Wikipedia <https://en.wikipedia.org/wiki/Anonymous_function> Lisp was the first language to use anonymous functions (introduced in 1958). [Stephen Turnbull]
Wikipedia lists the anonymous function syntax of 40+ languages <https://en.wikipedia.org/wiki/Anonymous_function#Examples> and only 5 (Lisp, Scheme, Python, Ruby, and Maxima) use the "lambda" keyword. Haskel uses a "\" which I'm pretty sure is supposed to look like the lambda symbol, but even that syntax seems unpopular too. [Stephen Turnbull]
I wasn't aware that Guido considered "range" to be warty. I like the way it mimics slicing syntax. It makes it easy for me to remember. It seems like a very pragmatic design. [Steven D'Aprano]
Secure in the knowledge that Guido probably isn't reading this and won't contradict me *wink* I'm going to try channelling him.
SUMMON THE GREAT CREATOR! I wonder if I say his name three times... Guido Van Rossum! Guido Van Rossum! Guido Van Rossum! [Steven D'Aprano]
I think he would regret "def expressions", but not because of the range reason.
I think its because he likes the relatively strict demarcation between statements
(I don't know why Gmail's quotes screw up formatting...) I don't think that's the reason those expressions have different formats than their statement counterparts. Expressions allow for more flexible arrangement than expressions because the order of execution of an expression doesn't have to follow the order of declaration. While it's more natural to say "do something to each item in this collection that meets some condition" you can't access variables before they're declared in statements so you have to tell the computer explicitly that you're looping over some iterable first. Expressions allow you to be more expressive. You don't have to put your edge-case checking up-front and in the way. When 99.9% of the time you just want: x = y you can shove the edge-case checking to the side and let the core logic shine: x = y if not edge_case else special_value # extra spaces added for emphasis besides: result = if condition expression else expression is super awkward to read out loud. That's not how I think at least. I've never hears someone say, "My child's name will be if it's a girl Sally otherwise Billy." All of the expressions use either the same or similar keywords or symbols *except* def and lambda. func = def <args>: <expression> Is about as different from the statement form as "x := y" is from "x = y". No name, no parentheses for the arguments. Finally, I know you've heard the other half of my anti-lambda manifest, but I don't know if Stephen Turnbull has, so I'll briefly present it again. It's not just the name "lambda" that bothers me, it's the arrangement of the logic and signature. I believe that the expressiveness that allows comprehensions to put the core logic in front of the less important (for readability) loop and filtering constructs, anonymous functions could have been arranged to put the logic in front of the (almost always) less important signature. The reason I say the signature is almost always less important is because one almost always uses an anonymous functions as an argument (key-function, callback, map, reduce, filter, etc.) to something that already defines the call signature it expects. Consider the alternate form: <expression> with <args> (thought there are many alternative possibilities) hand = sorted(cards, key=lambda card: value[card.suit] if card is not wild else max_value) hand = sorted(cards, by=value[card.suit] if card is not wild else max_value with card) # notice how unsurprising it is that the signature is "card" Oh wait... Did I accidentally replace "key" with "by"? Huh... It seems to make more sense even though the jargon is a "key function"... Oops! ;) Note: if this were a full proposal, lambdas with complex arguments or in certain situations would require parens: (<expression> with <args>) On Tue, Aug 21, 2018 at 9:31 AM, Steven D'Aprano <steve@pearwood.info> wrote:

On Wed, Aug 22, 2018 at 3:56 AM, Abe Dillon <abedillon@gmail.com> wrote:
I've never hears someone say, "My child's name will be if it's a girl Sally otherwise Billy."
"My child's name depends on gender - if it's a girl, Sally, otherwise Billy." Seems fine to me. You can always come up with something awkward in a particular order, but it's not the order that made it awkward.
Okay, let's read that. hand = # we're assigning this to the name 'hand' sorted( # calling the function named 'sorted' cards, # positional argument, whatever's in the 'cards' variable by= # keyword argument, what comes next is the 'by' argument value[card.suit] # subscript 'value' with 'card.suit' if card is not wild # yep else max_value # so we have an alternative with card # WAIT WAIT WAIT Once you get to 'with card', you have to go back and completely reinterpret everything prior to that as a function. You have to scan back and go "hang on, so exactly how much of this is getting wrapped up into a function here?". Contrast the Python version: hand = sorted(cards, key=lambda card: value[card.suit] if card is not wild else max_value) hand = # we're assigning this to the name 'hand' sorted( # calling the function named 'sorted' cards, # positional argument, whatever's in the 'cards' variable key= # keyword argument, what comes next is the 'key' argument lambda card: # a function taking one argument value[card.suit] # subscript 'value' with 'card.suit' if card is not wild # yep else max_value # so we have an alternative ) # and we're done The only part where you have to back up and change your interpretation is when you hit "if card is not wild", which reads well enough to justify the odd ordering. (JFTR, I wouldn't implement a deck of cards this way. It implies that there is exactly one wild card, where many decks of cards have at least two. In English, "card is not wild" can be interpreted as a membership check, but in Python, it is only an identity check; you're capitalizing on false readability by using this notation.)
Oh wait... Did I accidentally replace "key" with "by"? Huh... It seems to make more sense even though the jargon is a "key function"... Oops! ;)
I'm sure it would make even more sense if you wrote it this way: hand = sorted(cards, by="suit") That's how SQL works - you just name the column that you want to order the results by. But if you think "by" is a better keyword here, start explaining why your ordering is done with an anonymous function, not with an attribute name. ChrisA

[Chris Angelico]
The revelation that it's a function should come when you read the "by" or "key". If you don't know what that parameter is, then that's where the "wait wait wiat!" should happen. Then type "help(sorted)" in a console or something. Another hint can come from the appearance of an undeclared variable: card. (I know, I know: I didn't declare several variables, just imagine that 'card' is the only variable not previously declared). It's no more surprising than reading a comprehension: initials = {person.name[0] for person in people if person.name} initials = # we're assigning this to the name "initials" initials = { # it's a dictionary or set of something initials = { person.name[0] # I'v never seen "person" before, this must be a comprehension or something # anyway, no ":" means it's a set of the first letter of each person's name intiials = { person.name[0] for person # WAIT WAIT WIAT WHAT?!? Just kidding, I saw this coming... [Chris Angelico]
If the logic is simple enough, you can just use a reference to the method from the class: hand = sorted(cards, by=Card.suit) # where Card is the class That's why I tend to use a more complex example. Otherwise the lambda isn't really justified. [Chris Angelico]
JFTR, I wouldn't implement a deck of cards this way.
I don't implement decks of cards often, but in toy problems; I find just using 2-character strings works fine: Ace_of_spades = "As" Ten_of_hearts = "Th" etc... That can easily be extended by a named tuple initialized with unpacking: Card = namedtuple("Card", "rank suit") Ace_of_spades = Card(*"As") [Chris Angelico]
It implies that there is exactly one wild card, where many decks of cards have at least two.
I don't know of many games that have wild cards, but that's a simple remedy: hand = sorted(cards, by=value[card.suit] if card not in wilds else max_value with card) [Chris Angelico]
I promise that wasn't my intent. Since both my proposed form and the lambda form use the same expression, it doesn't really tip the balance in favor of my argument. Also, most toy card problems I work with use a finite, immutable set of cards, so identity checking isn't *that* weird. On Tue, Aug 21, 2018 at 1:12 PM, Chris Angelico <rosuav@gmail.com> wrote:

On Wed, Aug 22, 2018 at 4:56 AM, Abe Dillon <abedillon@gmail.com> wrote:
That right there is unacceptable. You should not have to know the destination to understand what something fundamentally is. You can't redefine language syntax based on the function being called. ChrisA

[Chris Angelico]
That right there is unacceptable. You should not have to know the destination to understand what something fundamentally is.
You don't *have* to know what the parameter "key" is to know that (value[card.suit] ... with card) is a function. You can identify that it's a function just by reading the full expression. However, if you don't know what "key" is, then it'll cause far more confusion than the late declaration of the function's parameters. [Chris Angelico]
You can't redefine language syntax based on the function being called.
That's not at all what I suggested. You were walking through my example from the reader's perspective. I was explaining how the reader will often have plenty of context about what they're reading before they get to the signature declaration. Whether it be because they know what the "key" parameter means or because they know "card" is undeclared or both. I never claimed the language syntax should be based on the function being called. func = value[card.suit] if card not in wilds else wild_value with card Works independent of the function being called. It's just not a common use case because it obviates the expressiveness of anonymous functions. You might as well use a "def" statement. The thing that makes callbacks difficult is not knowing how they're called. I tried to throw a little JavaScript into my curriculum once thinking "how bad can it be?" and suggested my students work on a project using the Force Directed Graph from D3.js <https://bl.ocks.org/mbostock/1062288>. That was a HUGE mistake not because anonymous functions are confusing but because the example (at the time) had no documentation at all (like this one <https://bl.ocks.org/mbostock/4062045>) and used mysterious callbacks everywhere. The main documentation for D3.js is super difficult to navigate, when all you want to do is slightly modify one of the examples (use svg images for the nodes and have stats display "on mouse over"). If you don't know what "".join() does, then you're going to have trouble making sense of: def initials(person): return "".join(name[0] + "." for name in person.names if name) The late assignment of the name variable will NOT be your main source of confusion. If you do know what "".join() does, then it should take you much less context to realize you're reading a generator expression. By the time you read the yet-to-be-assigned "name" variable you should be tipped off. On Tue, Aug 21, 2018 at 1:58 PM, Chris Angelico <rosuav@gmail.com> wrote:

On Wed, Aug 22, 2018 at 6:24 AM, Abe Dillon <abedillon@gmail.com> wrote:
Python's parser is *deliberately* incapable of backtracking this far in its definition of syntax. So if you want to have something where the first long slab of it is entirely acceptable as an expression, right up until you get to the "with" at the end, it's not going to work. You then said that it was the parameter "key" that told you that this would be a function, which is also unacceptable in Python syntax. So how do you intend to do this? And you still haven't done anything to show that this is actually better than "lambda card:" at the beginning. I'm done. ChrisA

[Chris Angelico]
Python's parser is *deliberately* incapable of backtracking this far in its definition of syntax.
Can you explain how far the parser is capable of backtracking? It seems like <expression> with <signature> would require a similar amount of backtracking to ternary expressions: <expression> if <condition> else <expression> If the preceding expression is the same in both cases, then the parser needs to backtrack just as far when it finds an "if" as when it finds a "with". [Chris Angelico]
You then said that it was the parameter "key" that told you that this would be a function, which is also unacceptable in Python syntax.
That was *never* a statement about syntax. It was about the context clues a reader has, not the parser. The proposed syntax: <expression> with <signature> is an expression that evaluates to a function object regardless of any parameter or any function it might or might not be passed to. My argument is simply: Most cases where an anonymous function is more expressive than a named function are also cases where, *from the perspective of a human reading the code*, the signature is noisy preamble that gets in the way of the expression. In psuedo code, people tend to write things like:
hand = sorted(cards, by=card.suit)
Obviously that wouldn't compile because the computer doesn't know what "card" is. However;
hand = sorted(cards, by=lambda card: card.suit)
puts a bunch of noise that's mostly of interest to the computer in front of the expression that's of interest to the reader. There is precedent for late-variable-binding in Python expressions already (e.g. comprehensions), so it makes sense to me that the expression version of function declaration could also bind the signature after the main expression. The same logic follows for mappers, reducers, filters, callbacks, event-handlers, etc. [Chris Angelico]
So how do you intend to do this?
I don't intend any of this to make its way into Python. It's a case study of expression design. It's interesting to me to explore such alternatives. It's fine to prod it and examine its flaws as Jonathan Fine has. [Chris Angelico]
And you still haven't done anything to show that this is actually better than "lambda card:"
I'm trying to, but I also have to answer all your misconceptions about the idea (like that the syntax is function or parameter-dependent). [Chris Angelico]
I'm done.
OK. I'm sorry if I upset you.

On Wed, Aug 22, 2018 at 8:45 AM, Abe Dillon <abedillon@gmail.com> wrote:
I have to defer to someone who knows in more detail here, but the parser will look ahead one "token", whatever a token is. (Technically it doesn't backtrack, it looks ahead - same difference.) In order for the ternary-if to work, the expression before the if has to be of a more restricted type than just "any expression" (for instance, you can't put a lambda function there, unless you parenthesize it). But I'm not fluent in all the details, and I definitely am not comfortable citing exactly what the limits are. The last time I tried editing the grammar, weird things happened. ChrisA

[Chris Angelico]
Interesting. I really need to try delving into the nuts and bolts of Python. I didn't know that about ternary expressions. I don't know if you saw my recent discussion with Jonathan Fine, but he brought up some good points too.

Chris Angelico writes:
Tokens are basically keywords, identifiers, most single punctuation characters, and indentation. Some strings of punctuation are tokens by special dispensation.
It's not that it's a restricted expression, it's that a valid lambda will consist of a syntactically complete expression. If you then place "if" after that lambda without parenthesizing, the parser will think that the lambda contains the whole ternary expression because pretty much any Python expression has a value that can be implicitly cast to bool. Steve

Thanks, Stephen. That's interesting. So the parser can see one token past, for instance; what would be the end of an expression, see "if", and know to expand the AST?

Abe Dillon writes:
Yes, if you want to think about it that way. I think about it in terms of the parser receiving tokens one at a time, using to revise the AST, until it can't. Like a five-year-old building a fort by piling up pillows. She's done when she's out of pillows, or the whole thing falls over due to imbalance. She doesn't have a grand plan, she just puts pillows wherever they fit. At the point where no work can be done, the parser either has a token in hand, which is a syntax error, or it's at end of input. In the latter case, it either has a complete syntactically correct AST, or it's a syntax error. In the end it works the same as your description, but I don't think of it in terms of the parser knowing "where" it is in the program, but rather in terms of whether it can do more work on the AST with the token (or EOF) in hand. Only when it runs out of input does it "look at" what it's built so far to check if it's done. If you think of expressions having their own subparser, the model is a little more subtle. I think of the subparsers as being coroutines receiving tokens via (yield) from their parent. This implies that when the subparser actually returns an AST, the parent already has the token that the subparser balked at. In some sense, there's no lookahead in the sense of something you save away to fully process later, or pass to another actor to process. You're always operating on a current token. Steve

Stephen J. Turnbull wrote:
For understanding what kinds of things an LL parser can parse, it helps to have gone through the exercise of implementing a recursive descent parser. The classic way to do that is to write a function for each production in the grammar. E.g. if you have a production expr ::= term ['+' expr] then you would write a function structured like this: def parse_expr(): parse_term() if current_token == '+': next_token() parse_expr() What other stuff you do in it depends on what you want the parser to accomplish. If you want it to build a parse tree, you could do something like this: def parse_expr(): result = parse_term() if current_token == '+': next_token() operand2 = parse_expr() result = BinopNode(result, operand2) return result
Not so much where it is in the program, but where it is in the *grammar*. For example, if parse_term() gets called, it knows it must be looking at the beginning of a term. If the current token is not one of the ones that can begin a term, then there is a syntax error. The fact that a recursive descent parser always knows where it is in the grammar is useful, because it can be used to produce helpful error messages. For example, if it gets stuck in parse_term() it can say something like "I was expecting a term here, but this token doesn't look like the beginning of a term." Unfortunately, Python's parser doesn't seem to make much use of this. :-(
If you think of expressions having their own subparser, the model is a little more subtle. I think of the subparsers as being coroutines
That's kind of the way an LR parser works. An LR parser is more powerful than an LL parser, because it can effectively explore several possible parsings in parallel until one of them succeeds. But I don't think Python uses an LR parser, because its grammar is required to be LL(1). If you're interested in this stuff, I recommend either taking a computer science course or reading a good book about the theory of parsing. It will bring a lot of these concepts into sharp focus. -- Greg

Greg Ewing writes:
I deliberately decided not to go this route. I'm curious whether Abe found both posts useful. (Comparisons are invidious; please don't. ;-)
[Concise useful description of what this means and why it's useful elided.]
Unfortunately, Python's parser doesn't seem to make much use of this. :-(
Indeed, and that's part of why I chose the route I did. But the main point is that in the context of the particular example (the lambda swallowing the if-else expression if the lambda is not parenthesized), the "keep going until you can't" aspect of subpattern matching (used for ambiguity resolution) is the cause of the need for parentheses here.

On Tue, Aug 21, 2018 at 05:45:53PM -0500, Abe Dillon wrote:
Can you explain how far the parser is capable of backtracking?
Its an LL(1) parser, if I recall correctly, so if you look at the details of LL(1) parsing, that should answer the question. https://en.wikipedia.org/wiki/LL_parser But if I'm reading the Wikipedia page correctly, I think the answer is "no backtracking at all".
I don't think needs any backtracking. The parser doesn't have to read the "if" and then go back to re-read the previous expression. It can look ahead from the expression by one token, see the "if", and recognise it is a ternary if. -- Steve

Hi Abe First, I have reservations about the name lambda. But there's a lot of code out there that uses lambda, and I'd like that code to continue to run. You wrote:
func = value[card.suit] if card not in wilds else wild_value with card
I thought I'd try this, and variants, in the Python interpreter. I got # An expression. It's valid syntax, get run-time error.
value[card.suit] if card not in wilds else wild_value NameError: name 'card' is not defined
# An expression. It's valid syntax. Its value is a function. No run-time error.
lambda card: value[card.suit] if card not in wilds else wild_value <function <lambda> at 0x7ff815e2bbf8>
# If Python were enhanced, an valid expression whose value is a function.
value[card.suit] if card not in wilds else wild_value with card SyntaxError: invalid syntax
My understanding is that you prefer
How do you feel about this, as a means of defining an anonymous function?
with IDEN: EXPRESSION
We can't adopt it, of course, because it's already valid syntax, but with semantics.
Now for a trick question. Consider
fn = (lambda : EXPRESSION) This produces a function that has zero parameters.
How would you write this, using 'with'. Would it be:
fn = (EXPRESSION with) I think this looks rather odd.
-- Jonathan

[Jonathan Fine]
Yes. I'm under no delusion that lambda will be replaced any time soon. Nor do I believe any alternative I suggest will be enough of an improvement to warrant breaking the "there should be one and only one obvious way to do something rule". So I don't expect this conversation to lead to any change to the language, I just think my case that it's sub-optimal might inform future design decisions. Though it doesn't look like anyone finds it especially convincing. [Jonathan Fine]
Correct. My argument is two fold: 1) the name "lambda" is needlessly esoteric. 2) the format of lambdas is "backwards" I tried to focus on the name gripe in this thread because trying to explain both at the same time caused confusion. However, Stephen Turnbull's and (more so) Steven D'Aprano's comments made the format argument semi-relevant and I can't help getting on that soap-box... [Jonathan Fine]
How do you feel about this, as a means of defining an anonymous function?
with IDEN: EXPRESSION
I think it's better than lambda. I can't decide if I like it more than:
def IDEN: EXPRESSION
Because def is more clearly connected to function declaration and i'm somewhat sympathetic to the idea of expressionizing "with"-statements. The only reason I don't prefer:
EXPRESSION def IDEN
to
EXPRESSION with IDEN
Is that it looks weird to me. It just doesn't seem right. [Jonathan Fine]
That's a good point. I hadn't considered that. There are several possible formats that put the expression before the signature definition. The specific form isn't quite as interesting to me. I would even prefer something like:
def (EXPRESSION [<seperator> SIG])
Mostly because "def" could then have a double meaning: "define" and "deferred expression". I think that's kinda neat. My problem with putting the signature first is that it usually amounts to noisy preamble that gets in the way of the important code. In pseudo code you'd often write:
hand = sorted(cards, by=card.suit)
But obviously the compiler doesn't know what "card" is since it's never declared, so we write:
hand = sorted(cards, by=lambda card: card.suit)
Notice that the information that's important to the reader: the expression, is pushed behind information the computer needs but the reader probably doesn't care about. My claim is that in most cases, the signature is more noise than signal, so it should come after the expression. A function passed as a callback, key-function, mapper, reducer, filter, event handler, etc. has a mostly pre-defined call signature. In most other cases, you're better off using a named function. Thanks for your input! On Tue, Aug 21, 2018 at 3:51 PM, Jonathan Fine <jfine2358@gmail.com> wrote:

On Wed, Aug 22, 2018 at 4:56 AM, Abe Dillon <abedillon@gmail.com> wrote:
Fair enough. To be fair, I use decks of cards primarily for non-game usage (for instance, teaching data structures and algorithms - cards laid out on a table can represent a tree, heap, array, etc), and my decks of cards are artistic. A deck containing four suits of thirteen cards plus one joker would have 53 cards, which is a prime number; printing 54 cards lets you lay them out as 9 by 6 on a sheet, so it's easy to add a second joker. Some decks (I have an Alice in Wonderland themed deck) have *four* jokers. As such, the most logical way to do this would be as an attribute of the card. Its jokerness is as much a feature as the clubness of another card. You can pick up a physical card, look at it, and say "This is a joker"; you don't have to see if it's in a list of specific known jokers. hand = sorted(cards, by=value[card.suit] if not card.wild else max_value with card) Honestly, though, it'd usually be more interesting to sort by rank within suit. What you're doing here would group the cards by suit, ignoring their ranks; more useful would be: hand = sorted(cards, key=lambda card: (card.is_wild, card.suit, card.rank)) Much cleaner. No conditionals needed. ChrisA

[Chris Angelico]
I do too. They're a great tool for visualizing and physically trying out different techniques. [Chris Angelico]
In most cases I've seen wild cards used, it's a declaration about a certain card (e.g. "Eights are wild." or "The 2 of clubs is wild."). I've found that if you're trying to model a game like poker or Monopoly, it's tempting to add complexity to simple objects, but it can lead to problems later on. A card doesn't know if it's wild. That's a function of the game being played. An ace may be high or low. On Tue, Aug 21, 2018 at 2:06 PM, Chris Angelico <rosuav@gmail.com> wrote:

On Wed, Aug 22, 2018 at 6:33 AM, Abe Dillon <abedillon@gmail.com> wrote:
Well, okay. Then you should check if the card is a joker, rather than checking if it's wild. That means your sort function is "by suit, and within that by rank, but jokers are at the end" (ignoring wildness). That said, though... I've seen and used a Canasta deck of cards, which have game-specific information printed on them. Physical cards. So there's precedent for that! ChrisA

On Tue, Aug 21, 2018 at 01:56:16PM -0500, Abe Dillon wrote:
The revelation that it's a function should come when you read the "by" or "key".
I disagree. The most important fact is that it is a function, not specifically what it does. Consider: widget.register(value[a](x) with x) (As per your earlier example of ternary if operator, I've inserted spaces to emphasis the gap.) At first it looks like you are evaluating value[1](x) eagerly, right there in the method call, and then you have to backtrack and change your expectation about what you just read when you get to the end and see the declarations. Even Forth, which (apart from its use of extremely concise commands) is most (in)famous for backwards things writing in Reverse Polish Notation, or programming by Yoda *wink* nevertheless puts the "function declaration" before the body. Classically, you define a function like this: : func DUP DROP ; The colon tells the interpreter to start compiling a function named "func", DUP and DROP are the commands in the body of the function (in this case, a pointless combination), and the semi-colon says to stop compiling and bind the new function body to the given name. Classical Forth doesn't have named function parameters, but some RPN languages do, and likewise they come first. In the HP calculator RPN language, we write something like: << -> x << DUP DROP >> >> to grap an argument and assign it to "x". Given some sort of look-ahead, it's *possible* to put the parameter list at the end of the function body: def function: do_this(a) do_that(b) do_something_else(c) with (a, b, c=None) but I think you can see why that would be annoying. You don't even know which names are global and which are parameters until you get to the very end of the function. Blah. The same applies to function expressions. Given the function body: value[a](x) which of value, a and x are global names and which are parameters?
If you don't know what that parameter is, then that's where the "wait wait wiat!" should happen.
"Wait wait wait!" should ideally never happen. In programming, surprises are not a good thing, and they're even less good when they are retroactive. "Ha, fooled you! You thought you were dealing with an eagerly evaluated expression, but it was a deferred function body declaration instead! Mwahahahaha!!!" -- Steve

On 22/08/18 07:11, Steven D'Aprano wrote:
This, by the way, is why think using the same syntax for function definition and generator definition was a mistake. It's only when I reach a "yield" statement that I realise my expectations for this code are wrong. (That was a decision made a long time ago, and I'm not fool enough to think that there's any benefit in trying to change it now. I can still be a grumpy old man over it, though.) -- Rhodri James *-* Kynesim Ltd

Hi Rhodri You wrote:
This, by the way, is why think using the same syntax for function definition and generator definition was a mistake. It's only when I reach a "yield" statement that I realise my expectations for this code are wrong.
Here's something that might help, and surprise, you. This has been present since Python 2.5.
I think what's happening is this. Even though the None-guarded yield has been optimised away, it leaves a residue. Namely, that there's a yield in the function. Hence fn() is an iterator. Having explained the surprise, here's how it can help you. Suppose you have a long function body, with a single yield at the bottom. If you write like this: def my_very_long_function_with_one_yield_point(...): if None: yield # This is a generator function. then the next programmer can know immediately that it's a generator function. -- Jonathan

On 22/08/18 14:38, Jonathan Fine wrote:
If by "help" you mean "make even more confused", then yes. Surprise is a given with generators, as I said.
Ew. I'd prefer this way of doing it: def my_very_long_function_with_one_yield_point(...): # This is a generator -- Rhodri James *-* Kynesim Ltd

On Thu, Aug 23, 2018 at 3:56 AM, Rhodri James <rhodri@kynesim.co.uk> wrote:
Actually, it fails unless fn returns some sort of iterable.
Or you could use a return type annotation. Why should generator objects be special? A generator function is very similar to a function that returns a list, except that it can yield values as it gets them, rather than batching them up to the end. A generator function is a function which returns an iterable object of the type "generator". How is it different from a function that returns an integer? They return different things. How do you show what a function returns? You annotate it, put it in the docstring, put it in external docs... It's a function. It does something, it returns something. That's it. ChrisA

Fwiw, I usually don't do def foo(): if False: yield None But simply: def foo(): return () That the returned iterable is not a generator seldom matters. Stephan Op wo 22 aug. 2018 21:17 schreef Chris Angelico <rosuav@gmail.com>:

Rhodri James wrote:
This, by the way, is why think using the same syntax for function definition and generator definition was a mistake.
I think I remember arguing the same thing back when generators were being devised. But there are arguments the other way too. From the outside, a generator is just a function that returns an iterator -- the fact that it works by yielding is an implementation detail. When you write an ordinary function that returns an iterator, the fact that it returns an iterator needs to be conveyed some other way, such as by its name or documentation. if you can do that for an ordinary function, you can do it for a generator just as well -- and probably should, so that you can tell what it returns without having to look at its definition. If the name of the function indicates that it returns an iterator, or there's a docstring at the top what says so, then you won't be surprised when you find a yield in it somewhere. -- Greg

On Thu, Aug 23, 2018 at 9:02 AM, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
def gen1(x): return iter(range(x)) def gen2(x): i = 0 while i < x: yield i i += 1 def gen3(x): if i % 2: return gen1(x) else: return gen2(x) Which of these three are generator functions? Technically only one of them is... but how would it make any difference? ChrisA

[Steven D'Aprano]
I was trying to say that the context almost always gives away that the reader should expect a function. Again, the pseudo code: hand = sorted(cards, by=card.suit) Is usually enough for most people to understand. When you add in what the computer needs to make the whole thing mechanically unambiguous: hand = sorted(cards, key=lambda card: card.suit) You can see the noise added compared to the pseudo code. The difference (to me) looks like this: hand = sorted(cards, by#=#############card.suit) Ideally, we could move that noise out of the way so that the intent is more clearly expressed: hand = sorted(cards, by=card.suit ########## Functions, variables and parameters are normally named such that they give away lots of context (or they should be). Context that's available to the reader but not the computer. [Steven D'Aprano]
Consider: widget.register(value[a](x) with x)
First, how is your example any worse that the delayed binding of generator expressions? widget.register(value[a](x) for x in things) Of course the context of what they're reading builds as they read it. You could put those spaces anywhere: widget.register(value[a] (x) for x in things) Delayed binding works because human readers can deal with a little ambiguity in what they're reading especially if it means putting the intent of the code before the book keeping. If we're assuming a naive reader who's never seen the widget.register method and method and variable names that are pretty ambiguous (not unheard of, especially in anonymous functions) then I would say the blocker is not knowing what widget.register is in the first place. If you don't know that, then what point is continuing to read? Will knowing the kinds of object being passed clear everything up? widget.combobulate(5, "elephant", True) Once the reader has encountered widget.register they'll know it takes a function as an input. Just like anyone who's used time.sleep will be thrown for a loop as soon as they see lambda in: time.sleep(lambda x: value[a](x)) [Steven D'Aprano]
Yes! Common ground! <doing my common ground dance> Named functions serve a different purpose than anonymous functions. They usually handle situations where the interface is more important than the implementation. def square_root(x): ... Better spit out the square root of whatever number I give it. I don't care how. Anonymous functions are almost always used in contexts where the interface is implied and the important bit is *what* it does: ui_element.on_mouseover(<what to do> with event) [Steven D'Aprano]
The same could be said of the value[a](x) in: widget.register(value[a](x) for x in things) [Steven D'Aprano]
It happens when someone has never seen the map function used or sorted used with a key function. It happens during the time where reading code is hard to begin with. The "wait wait wait" happens when you don't know what map is. Once you learn that, then you learn that the first parameter is a function. Then whenever you see map, you should expect the first parameter to be a function. No amount of broadcasting that the first parameter is indeed a function will cure the confusion of not knowing what map, or wiget.register is. *Having said all that:* Jonathan Fine pointed out that the <EXPRESSION> <SEPARATOR> <SIGNATURE> format that I've been championing (where I've been using "with" for the separator) has a subtle flaw where empty signatures are pretty awkward: d = defaultdict(100 with) It *kind-of* works with "def" and you read it as, "the preceding expression is deferred" followed by an *optional* signature declaration. d = defaultdict(100 def) But it's not great. Another alternative is to use some (ideally short) prefix and making the signature declaration optional: <PREFIX> <EXPRESSION> [<SEPARATOR> <SIGNATURE>] d = defaultdict(def 100) hand = sorted(cards, by=def card.suit with card) of course there are many possible choices for the prefix and separator and subtle alterations like: hand = sorted(cards, by==>card.suit with(card)) . # where '=>' is the prefix, it just blends nicely or: d = defaultdict(100 with()) Anyway, none of that interests me. What interests me is the recognition of *why* expressionization of statements often leads to a re-ordered version of the original. My thesis is that expressions are slightly more flexible than statements which allows for a more expressive ordering that is sometimes better for readability. I think it's important to understand that if we ever expressionize other statements like try-except, with, etc.

On Wed, Aug 22, 2018 at 12:11:40PM -0500, Abe Dillon wrote:
You are judging that from the perspective of someone whose native language makes it easy to say "sorted by foo" (for some value of foo). We shouldn't judge syntax proposals just on the cases that are carefully chosen to showcase them at their best. Especially not trivial cases. Here is a line from the importbench tool in Python 3.5: def bench(name, cleanup=lambda: None, *, seconds=1, repeat=3): Under your proposal, that becomes: def bench(name, cleanup=None with ???, *, seconds=1, repeat=3): except I'm not really sure what goes in the ??? for an empty parameter list. But whatever it is, do you still think it is obvious that people will recognise "None" to mean a function without having to backtrack? And from the threading tests: t = threading.Thread(target=lambda: None) difflib tests include this call: sm = difflib.SequenceMatcher(isjunk=lambda x: x == ' ', ...) which becomes: sm = difflib.SequenceMatcher(isjunk=x == ' ' with x, ...) The expression x==' ' doesn't look like a function to me.
Ideally, we could move that noise out of the way so that the intent is more clearly expressed:
So you say. I say it isn't noise, and if you ask me to express my intent, I'll state that it is a function first and at the beginning of the expression, not the end.
Who says its worse? I think they are equally as problematic. Many people have trouble with comprehension syntax precisely because it breaks left-to-right order. I think we ought to be cautious about emulating that elsewhere. -- Steve

On Thu, 23 Aug 2018 03:44:07 +1000, Steven D'Aprano wrote:
On Wed, Aug 22, 2018 at 12:11:40PM -0500, Abe Dillon wrote:
Hold that thought.
Okay, so I'm trying to follow along, and not jump in with another "me, too" response. Statements and expressions don't read from left to right. Blocks and functions don't read from top to bottom. Some people read programs from the inside out, assembling bigger and bigger building blocks until the entire program is just a building block. Others read programs from the outside in, decomposing really blg blocks until the remaining blocks are small enough to see and understand without further decomposing. Reading a program, let alone figuring out what it does, let alone figuring out what it's supposed to do, is not a simple single pass process. Something has to come first, and something has to come next, and something will end up coming at the end. Regardless, the reader will have to save some context, or go back and look at the beginning again. So is it better to see the definitions first, and the logic second? Or is it better to see the logic first and the definitions later? I don't know; it depends. It may even vary over time inside the same code base. When you talk about intent, I think about use cases. In the difflib code I quoted above, is the intent to define a function, or to instantiate a SequenceMatcher? Well, no, it's probably to compute some sort of difference. Instatiating a SequenceMatcher and defining isjunk are details. So you're both wrong. :-P Or you're both right. :-/ A large part of my previous job was digesting papers written by economists and mathematicians, and then translating the ideas and algowithms in those papers into code. Sometimes, I'd see stuff like this: Given x = the width of a widget and y = the price of that widget, let f(x, y) be x + y. And sometimes, even in the same paper, I'd see stuff like this: Let f(x, y) be x + y, where x = the width of a widget and y = the price of that widget. Which one is harder to read, or expresses the intent better? If that's what we're down to, then an assignment operator is a trivial exercise. Dan

On Wed, Aug 22, 2018 at 06:50:29PM +0000, Dan Sommers wrote:
In this case, "intent" could refer to (for example): Should we accuse Fred Bloggs of plagarism or not? +- decide whether two documents came from the same source; +- decide whether the diff between two text strings falls within some threshold; +- initiate and use a SequenceMatcher object; +- provide an isjunk predicate function; +- implement a specific predicate function. Because we are talking about lambda syntax specifically, I didn't think the higher hierachies of intent were relevant, so I didn't mention them. I thought we could focus on the two relevant to the syntax we're discussing: Provide an isjunk predicate function; +- implement a specific predicate function. and take the higher levels as given. Given those two levels, "Provide a predicate function" is at a higher level than the implementation of that predicate function. I'm sorry if that wasn't clear. -- Steve

On Thu, 23 Aug 2018 21:40:12 +1000, Steven D'Aprano wrote:
Yes, the discussion is/was about lambda syntax, and about how quickly I (or someone else) can recognize that isjunk is being defined as an anonymous function. Perhaps I missed that the larger context had already been established. To focus my argument within your clarification: if I have all of that context, then I don't have to parse the code to know that the isjunk parameter is a function. And if parsing the anonymous function gives you (the generic you) that much trouble, then please break it out into a def statement instead. Flat is better than nested. IIRC, you push for named functions in all but the most trivial cases anyway (and I tend to agree). Dan

Replying out of order: [Steven D'Aprano]
I know I tend to write long-winded responses, but please read them fully before replying. I covered this. [Steven D'Aprano]
But whatever it is, do you still think it is obvious that people will recognise "None" to mean a function without having to backtrack?
It's not clear what you mean by backtracking at this point. cleanup=None with() requires no more backtracking than any other compound expression. cleanup=children.oldest().room doesn't tell you what kind of object is being assigned to cleanup. Is it a function? Who knows? Even if you know what 'children' is and what the 'oldest' method returns, you still don't know what's being assigned to cleanup without reading the entire expression. There has never been a guarantee that expressions evaluate left to right simply by virtue of the fact that an order of operations exists. The LL(1) parser limits parsing complexity to expressions which require at most one token look-ahead. Usually (I'll come back to this) that isn't hard for humans who process text in chunks of multiple tokens at a time. [Steven D'Aprano]
And from the threading tests: t = threading.Thread(target=lambda: None)
t = threading.Thread(target=None with()) seems pretty straight-forward to me. [Steven D'Aprano]
sm = difflib.SequenceMatcher(isjunk=x == ' ' with x, ...) The expression x==' ' doesn't look like a function to me.
You don't think that perhaps that's because it's brand new syntax? x=='' doesn't look like a function because it's not a function. You could play the same game with literally any compound expression:
func = ", ".join
", " doesn't look like a function to me! [Steven D'Aprano]
Don't you think that depends on the situation at all? Don't you think there are cases where the fact that you're passing a function and the call signature of said function are exceedingly clear from context? ui_element.on_mousover(<do something> with event) We already have a way to declare a function signature first. If you think it's paramount, then just def it. If you honestly don't understand my position at all. If it's always a surprise to you that ", ".join() takes an iterable of strings or that sorted takes a key-function that takes element from the iterable being sorted, or that on_mousover takes a function that takes an event object etc. etc. etc. then I guess I've never met anyone quite like you. I don't know how to communicate my point of view any better than I already have. [Steven D'Aprano]
You are judging that from the perspective of someone whose native language makes it easy to say "sorted by foo" (for some value of foo).
This argument is such a tiring distraction. Please stop. If it's all just random symbols to some non-english speaker, then It doesn't matter either way to them. They can still deal with tokens in the same way as the LL(1) parser. Only one look-ahead. That's not at all how the world works, but I don't have the energy to get into that discussion right now. I've been writing a veritable novel on my views on lambda for over a week now and people keep re-tredding the same ground. [Steven D'Aprano]
We shouldn't judge syntax proposals just on the cases that are carefully chosen to showcase them at their best. Especially not trivial cases.
We can judge it by examining cases where it might be problematic, but there's no way to keep people from abusing coding constructs to produce unreadable code, so just throwing out random chunks of code like a.b[c:d]-e**f(g, h=i) + {j & k, l*(m-n(o,p))} with e, k then saying "looks bad to me" offers no insight into the pros and cons of the proposal. Well, yeah. It looks bad because it's terrible code. It feels like you're not even trying to understand the basic premise of my position. Otherwise, I would be delighted to move past the simplified examples and on to more complex and probably troublesome counter examples. Hell, we can talk about how this would effect blind space aliens who can only hear ultra-sonic chirps and are essentially incapable of learning English after we get past this roadblock...

On Wed, Aug 22, 2018 at 06:28:45PM -0500, Abe Dillon wrote: [Steve -- that's me]
Yes, I accept that's not clear. Sorry. What I mean is that moment of having to reinterpret what you're reading. I start to read code, see that its assigning None to a parameter, and then a moment later have to re-interpret what we just read: None is not the argument, but the body of the function which is the argument. In linguistics that sort of thing is called a "garden path sentence" and research demonstrates readers take longer to comprehend them than sentences which don't require backtracking (re-interpretation). https://en.wikipedia.org/wiki/Garden-path_sentence Sometimes that's a good thing, if you're making a joke. But in general, they're not great for readability. Since your argument hinges on readability, that's a problem.
But at no point in reading "children.oldest().room" do you have to go backwards and re-intepret what you thought you saw. Even if the expression involves right-associative operators: children ** oldest ** room the worst that you have to do is defer thinking about children (push it onto the stack of short-term memory) until after you've thought about oldest**room. Now human memory has a very shallow stack. We struggle to hold more than approximately "seven plus or minus two" items in memory at a time. And of course people often forget that ** is right-associative (I know I do). But syntactically, there's no mental backtracking required. I'm not claiming that your suggested syntax is impossible in a LL(1) grammar like Python. I don't know. But I'm responding to your earlier assertion that it ought to always be obvious in context that you are looking at the body of a function, before you see the "with" keyword. As evidence for this assertion, you give examples where it is obvious: sort(sequence, by=card.suit with card) Sure, any English speaker familiar with the English idiom "sort by ..." can probably guess the semantics. That's great. But its not representative. We don't always have the luxury of expressions which read like English phrases: threading.Thread(target=None ... looks like the target is None, not a function, and we don't realise its not until we keep reading and learn at the very end of the expression that everything we saw before that point was part of the function body. It's great for English speakers that "sort by" appears in our code, but have a thought for those to whom it might as well be "pteg xb". Python is not just a language for English speakers, and if we're going to claim a readability advantage, we ought to at least acknowledge that not everyone will have that advantage, and not exaggerate the magnitude of that advantage by using words like "almost always".
There has never been a guarantee that expressions evaluate left to right simply by virtue of the fact that an order of operations exists.
That's fine, because I never said they did. It would be pretty foolish of me if I did, given that exponentiation is right-associative, and that we have comprehensions and ternary if expressions.
I know that. But you stated: "I was trying to say that the context almost always gives away that the reader should expect a function." The difflib example is a real, not made up, example that goes against that. The context "isjunk" sounds like it might be a flag, not a function, and the code x==' ' supports that interpretation right up to the moment you read "with x" part, at which point you have to re-interpret what you've been reading.
Indeed. I don't deny that there are expressions where if you truncate at a certain point, the code up to that point looks like a valid (sub-) expression of a different type: spam ∆ eggs If you truncate just before the ∆ you get a valid subexpression "spam" which may not be the same as the expression "spam ∆ eggs". But there aren't many places in Python where after truncating just before ∆, you interpret "spam" one way, but if you truncate after the ∆, you intepret "spam" a different way. Normally spam is spam no matter what follows it. In your earlier example ", " is a string, regardless of whether you have read up to the dot or not. Of course we could do this (LL(1) parser permitting) but the point I'm making is that this isn't a small change, and I don't think it will have the benefit you believe it will. The contrary: I think it will hurt readability, not help it. I think the benefit of moving the body of the function to the front is less than you think, and the cost of moving the syntax which distinguishes it as a function to the end greater than you think. I don't have objective evidence for these opinions, but I've tried as best as I am able to give the reasons why I believe this, and not just make it an assertion.
If you honestly don't understand my position at all. [...] then I guess I've never met anyone quite like you.
I'm a unique and special snowflake. https://i.imgur.com/W3ljlBg.jpg
I don't know how to communicate my point of view any better than I already have.
I understand your position. I just disagree with it.
When you are claiming an advantage, if that advantage doesn't actually apply, then its not an advantage, is it? I'm not going to stop using a valid argument just because you don't like it.
Good thing I didn't do anything like that. Abe, you are attacking a strawman. I didn't give made-up deliberately awful code. I took existing code from the standard library, and translated it to your proposed syntax. These "random chunks of code" are a non-issue. I never suggested examples like that, and I haven't seen anyone else do so either. -- Steve

Michael Selik schrieb am 14.08.2018 um 21:42:
This is supported by education research. Some light Googling found a study on the topic [0] that is consistent with my own observations.
OTx2, and no offence, but … this is supported by research as well. People tend to search just long enough to find the link that backs their … observations. :) Stefan

On 14 August 2018 at 16:42, Michael Selik <mike@selik.org> wrote:
"until after" != "forever". A jargon might be just an acronym, a word or few words, meaningless for someone who doesn't know what it means [sic], but even for this person the jargon is useful: he/she can look for information about it. Teaching the other way around to let the student grasp the "mechanical procedure" before its name doesn't change anything regarding the names. You can make everyone memorize the algorithm for adding base-10 whole numbers by hand without teaching the students words like "adding" or "sum", not even the "+" symbol. But it would be a confusion if you use any other symbol or word to replace these "maths jargon" ones, and you shouldn't avoid the socially used names/symbols just because you're teaching that stuff for kids who still doesn't know them. And I'm aware of students complaining they can't remember something they've learned (or simply they didn't know someone was talking about what they know, a communication issue) because they didn't know the name (not even for searching in the web, a dictionary, whatever...). I really regret that I complained when expressions like "modus ponens" and "disjunctive syllogism" were teached to me during a class in 2004, that day I thought these stuff were so obvious that they shouldn't have a name. Until I found, later, that I needed to know these names in order to understand some stuff I was reading. These names might had been hard to memorize, but they were better than arbitrary names that no one else happens to use. Some of my worst teachers avoided the proper jargon forever, not just "until after" definitions/examples. Several classes here in Brazil tries to teach some concepts by forcing everything to be in Portuguese, like an "ideology of full translation", and sometimes the translated names are meaningless (no social context external to the class uses them). I got somewhat angry when I found that a lot of stuff I knew had other names in every useful social context, and I know who/what I should blame for that. Terminology is the first step when going into a new domain... an example, marked as "Important unit", can be found at https://www.statistics-made- easy.com/introduction-to-statistics/ *This introduction will teach you all the basic terms of statistics. It is important to understand them well before studying the unit about organizing data. The lessons are organized in a way to make the learning process as smooth as possible. Follow the logical order given here to study the lessons.* [...] It's tempting to use terms based on the origin of the concept,
historical odds and ends, or even jokes. [...]
Usually, you're not naming something new and unnamed... but sometimes the concept might have more than a single name. I think that's like irregular verbs: they're so common that they "break the patterns"; concepts that are spread/scattered everywhere might have a distinct name in each domain. Names should be useful to precisely express the concept in social contexts, but there's a context that should never be considered for that: the "teaching" one. If the concept itself isn't known by some people, why care about an alternative "non-jargon" name? A name doesn't belong to a person or a class, but to the people who can use/understand it, and I believe using proper jargon instead of alternative "simplified" names should maximize that. It's the social expressiveness towards people who already know the concepts that should be emphasized, not some other arbitrary "simplification" goal (e.g. minimize the number of characters, only use English, ...). IMHO, avoiding jargon sounds like avoiding teaching. In the case of new Python stuff, avoiding the socially standardized terminology is an act of isolation/seclusion. -- Danilo J. S. Bellini --------------- "*It is not our business to set up prohibitions, but to arrive at conventions.*" (R. Carnap)

Michael makes some reasonable points, but I think the very premise of this thread is putting the cart before the horse. As educators, if we fail to teach the technical language of a field to our students, we are failing to prepare those students to enter that field. Technical jargon is the language of the field. If it makes teaching beginners more difficult, well, so it goes. Lots of things make teaching more difficult e.g.: - technical jargon; - expecting students to write code that runs; - expecting the code to run correctly; - having them do input validation and error handling; - and write documentation and comments for their code. Lambda is becoming a standard technical term in computing, even in languages which don't use that keyword. The official name for Java's anonymous functions is "lambda expressions": https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-Quick... Ruby has no fewer than three separate kinds of anonymous callable, blocks, procs and lambdas: https://medium.com/@AdamKing0126/ruby-whats-the-deal-with-procs-and-lambdas-... and the term is now used in C++, C#, LINQ and others, even if they don't use it as a keyword. https://duckduckgo.com/?q=lambda+expressions We should not focus too heavily on the earliest and most ignorant stage of people's programming life. That stage makes up probably less than 10% of their life as a programmer. Python is a general purpose programming language and we shouldn't shy from the appropriate use of technical terms in the documentation and the language itself. Python is not Scratch and the primary focus of Python the language is not education. Many people come to Python for the first time with one, two or ten other languages under their belt, and some of them even have a good grasp of computer science. We should not talk down to those experienced coders for the sake of those in the first year or so of their programming life. Scratch, for example, doesn't use the word "function" to describe functions. They use "blocks" (but not in the Ruby sense). This is, I suppose, fine for the average kid of age 8, if you think talking down to kids is okay (or necessary). But if we were designing Python from scratch today (pun intended), we surely ought not follow their lead. https://en.scratch-wiki.info/wiki/Custom_Blocks More comments below, following Michael's comments. On Tue, Aug 14, 2018 at 12:42:29PM -0700, Michael Selik wrote:
And the experience of educators like Chris teaching Javascript suggests strongly that no, it doesn't, since Javascript learners have just as much trouble learning the concept of "function" as Python learners have with "lambda". Chris' conclusion is that anonymous functions are inherently hard for many beginners to learn, regardless of whether the syntax is called "lambda" or "function". That matches my own observations, interacting with newbies on various mailing lists, as well as my own personal experience. I believe that many people have a lot of trouble grasping the concept of functions as first-class values capable of being passed to other functions as data. It requires a major rethink of the way we think of functions. We go from treating them purely as verbs: sort the list to nouns in their own right: process the sort # the what now? Not "process the sorted list", but reify the sort verb into an actual thing (an object or value) and then process that thing itself. This is mind-bending when you think about it, far more mind-blowing than the normal linguistic process of nouning verbs and verbing nouns. No wonder people take a while to get fully comfortable with the concept. It took me a long time to stop writing code like this: map(lambda x: len(x), sequence) instead of simply map(len, sequence). I doubt it would have taken any less time if it were map(function x: len(x), sequence) instead. Aside from having to learn the correct spelling ("lamdba"?) it was never the *name* that gave me trouble. Of course there is a cost for beginners to having to learn a name, and the less often the name is used, the longer it takes (unless it is extremely memorable). But that cost is paid for, with interest, later, as a journeyman or journeywoman programmer.
I agree. When I teach my students function transformations in maths, any time I use the technical terms translation, dilation and reflection, I follow up with the common terms shift, stretch, and flip, and vice versa. I make a point of always associating the imprecise plain English words with the precise technical terms. Nevertheless, it is important that I teach them the technical terms too. -- Steve

Hi Steve You and I have different experience, background and interests. You wrote
Python is a language with an enormous range. That is one of it's many strengths. Its users range from school-children, doing programming as part of their general education, all the way to research scientists, professional system administrators and the like. There are some really clever professional Python programmers. Some students learning Python, shock horror, won't enter the field. What proportion, I don't know. Some good statistics here would be helpful. For a different view of Python, take a look at * https://www.codeclub.org.uk/ * https://tutorial.djangogirls.org/en/python_introduction/ * https://codewith.mu/ * https://microbit.org/ * https://microbit.org/code/ The last two are important. 2016. All these children could be Python users. Very different from the students that you, as an educator, are preparing to enter the technical field of computer software. You further write
I'm very happy that Python works for the novice, and occasional programmers. Who have not aspirations to have a life as a programmer. Maybe they're musicians, or artists, or someone building a personal website. There are some really clever people in these fields, who write non-professional Python software. I'm very happy that Python works for high powered experts who are doing machine learning, numerical analysis, partial differential equations, big data and cloud system administration. To turn you statement around: We shouldn't focus too heavily on the latest and most learned stages of programming. Such activity, by hours spent, makes up probably less than 10% of humanity's time spent coding. Not disagreeing with you. Just viewing things differently. -- Jonathan

On 22/08/18 18:06, Jonathan Fine wrote:
Ditto for the Raspberry Pi, which is cheap rather than free but aimed at very must the same market.
In my experience teaching 12-15 year olds Python, not very different at all. Those that are interested in learning programming are interested in learning it properly, just like their older counterparts. Those that aren't interested in learning it aren't interested in learning it, no matter how much you dumb it down or talk it up.
If you're talking about Python coding I sincerely doubt that statistic. If you're talking about coding in general, it's meaningless. -- Rhodri James *-* Kynesim Ltd

On Wed, Aug 22, 2018, 12:40 PM Steven D'Aprano <steve@pearwood.info> wrote:
That long time is ongoing :-) You recently wrote in another thread: widget.register(callback=lambda: spam.eggs()) Instead of the slightly faster and definitely more direct: widget.register(callback=spam.eggs())

This isn't trying to snipe. I have written the exact same unnecessary circumlocution in my own code hundreds of times. Hopefully most of them simplified before release, but I'm sure not all. And I "wrote the book", as one says, _Functional Programming in Python_. Functions as sounds is a powerful but counterintuitive concept. On Wed, Aug 22, 2018, 1:38 PM David Mertz <mertz@gnosis.cx> wrote:

On Wed, Aug 22, 2018 at 01:38:03PM -0400, David Mertz wrote:
Hah, so I did.
Instead of the slightly faster and definitely more direct:
widget.register(callback=spam.eggs())
Except that doesn't work, since you are passing the result of calling spam.eggs as the callback, instead of spam.eggs itself :-) -- Steve

On Thu, Aug 23, 2018 at 6:24 AM, David Mertz <mertz@gnosis.cx> wrote:
This isn't quite the same, incidentally. It's (mostly) equivalent to: widget.register(callback=lambda *a,**kw: spam.eggs(*a,**kw)) I don't know of any situations where you specifically want to mandate that there be no arguments, but it's enough difference that I'd go check the docs before doing the refactor. (This is FREQUENTLY significant in JavaScript, where argument count mismatches are silent. So I'm used to seeing those shim functions.) ChrisA

Op wo 22 aug. 2018 18:40 schreef Steven D'Aprano <steve@pearwood.info>:
Civilization itself had trouble with the concept. Functions as mathematical objects in their own right were only conceived (late) in the 19th century. Church's lambda notation was the first way to write down a function without naming it, in the 1930's. And a proven consistent model for lambda calculus was only provided by Dana Scott in the 1970's! So clearly these mathematical developments haven't yet entered high school mathematics, which remains firmly set in an 18th century mindset, where we can interchangeably write down f or f(x). Unfortunately modern computer languages require more, so it is up to the comp sci teacher to fill the gap. But let's not blame Church's notation for that. λ f.(λ x. f(x x)) (λ x. f(x x)) lambda f: (lambda x: f(x(x))) (lambda x: f(x(x))) (Yeah I know it doesn't work in eagerly-evaluated Python). Stephan

Stephan Houben wrote:
Church's lambda notation was the first way to write down a function without naming it, in the 1930's.
That's debatable. It could be argued that calculus makes use of anonymous functions, e.g. the expression d/dx (x**2 + 2*x - 3) describes a function of x without giving a name to it. This means that
these mathematical developments haven't yet entered high school mathematics
is not entirely true -- anyone who's studied calculus has been exposed to the concept of an anonymous function, although it probably hasn't been explicitly described in those terms. -- Greg

Steven D'Aprano wrote:
I don't think it's all that much different. Consider the sentences: "Sorting is an interesting operation. It can be done efficiently or inefficiently." Here we temporarily bind the operation "sorting" to the pronoun "it". That's really the extent of processing that we do on functions. We don't actually do anything to the functions, we just give them temporary names. (Unless you go in for bytecode hacking or something, but beginners aren't going to be doing things like that.)
Is that because you found the concept itself difficult to grok, or did you just have trouble seeing opportunities to apply it? If you saw map(len, sequence) in someone else's code, did you immediately recognise what it was doing, or did you have to stop and think about it? -- Greg

[Steven D'Aprano]
It's not the responsibility of the tool to teach. My socket wrench doesn't have the history of socket wrenches inscribed on it, nor does it have any description of the different kinds of nuts and bolts. That's called the Single Responsibility Principal or SRP for short. Your job may be to educate, but that's not Python's job. [Steven D'Aprano]
We should not focus too heavily on the earliest and most ignorant stage of people's programming life.
The problem goes beyond just learning the term lambda, it can increase mental load on an already mentally demanding activity to have to translate an unfamiliar word every time you see it. It's lack of relation to anything else makes it hard to remember and hard to recall later. I've also argued that the very form of lambda expressions is noisier than it otherwise needs to be. It's not like noise is only distracting to novice developers. [Steven D'Aprano]
That stage makes up probably less than 10% of their life as a programmer.
My argument has never been about the high magnitude of the opportunity cost, just that there is one (IMHO) compared to a less jargon option. Better is better. period. Even if only improves the first 10% of your programming career. That's why I've said I don't ever think this discussion will lead to action. [Steven D'Aprano]
A Caterpillar Bulldozer is a professional piece of equipment. That doesn't mean they throw out basic tenants of good user interface design <https://en.wikipedia.org/wiki/Principles_of_user_interface_design> and take it upon themselves to teach the operator construction jargon through the interface. They still find it's better to use a red break light symbol with the aim of clearly communicating to non-experts. Just like a child's go kart! Even Python didn't find it necessary to teach me the word "ternary" for ternary expression. [Steven D'Aprano]
I don't think that one person's anecdotal evidence could be considered "strong" in the face of scientific studies. Especially when it's become clear that Chris was referring to a broad category of subjects that are only tangentially related to lambda expressions. [Steven D'Aprano]
That's not been my experience. [Steven D'Aprano]
Those topics have nothing to do with lambda expressions. You can demonstrate them without ever writing a lambda expression. The difficulty of those concepts doesn't inform the choosing of the name. You might as well name it "schubalu" and when I say "that's unnecessarily confusing" just say "well it's easier to learn the word 'schubalu' than it is to learn how Bloom Filters work!" Yup. I can't argue with that. I guess we should stick with "schubalu"... [Steven D'Aprano]
Aside from having to learn the correct spelling ("lamdba"?) it was never the *name* that gave me trouble.
Maybe not for you, but it's fresh enough in my mind that the name itself caused confusion. I know it seems minor, but back in the 'partial' thread, I was literally just talking about the name: lambda. Nothing else matters because it's all invariant. Callbacks will still be hard to learn. Functions as first class objects will still be confusing. All I'm talking about is a missed opportunity to choose a moderately better name. Just like function.partial vs. function.given. I didn't think my opinion would spawn 6 threads and hours of nit-picking. None of your discussion about the difficulty of functional programming informs the value of jargon over less jargon. When is it better to favor more common language, if ever? [Steven D'Aprano]
that cost is paid for, with interest, later, as a journeyman or journeywoman programmer.
Yeah, or never. My friend used to say he was in IT, then it was Dev Ops, now there's a new term. Or it may be that everyone knows what you mean when you say "anonymous function" and you didn't earn any interest for learning "lambda". After I graduated with my EE degree, I bought a bunch of vocabulary flash cards so that I could take the GRE and go to grad school. I remember wondering, "why the hell does every flash-card set have 'numismatics' in it?! I can never remember that damn word!" now I know it. It's never paid interest... [Steven D'Aprano]
Nevertheless, it is important that I teach them the technical terms too.
I find that beyond the basics: class, object, function, variable, argument, parameter, etc. Having students memorize jargon has limited value.

On Thu, Aug 23, 2018 at 10:44 AM, Abe Dillon <abedillon@gmail.com> wrote:
If the concept is utterly unfamiliar and the word is familiar, it creates a different problem: the false parallel. Let's suppose that, instead of calling them "lambda expressions", we call them "bacon expressions". Great! Lots of people know what bacon is. Is that an improvement? Definitely not. Some people love bacon and will wonder what anonymous functions have to do with their favourite food; others will wonder whether it's okay for a devout Jewish or Moslem person to use them. Technically this is true of "lambda" too, but for those who know Greek, it's like calling something an "S-expression", which is fairly obviously an abbreviation for something. ("Symbolic expression", I think? Someone might correct me there.)
Yes, you've asserted it. We've disputed it. You have yet to provide real evidence.
No, it probably called it an "if-expression" or "conditional expression" or something. "Ternary" just means it has three operands, so Python also has another very common ternary expression, namely the bounding: "5 < x < 10".
What broad category of subjects?
Okay! What's been your experience? Can you show us two comparable situations, one where you taught lambda functions in Python, and the other when you taught anonymous functions but without the word "lambda", and can demonstrate that one is harder than the other? My experience is that *highly intelligent* adult students, who have mastered many other concepts very rapidly, frequently have trouble with: * Asynchronous programming * Anonymous functions * The difference between serverside and clientside validation * How to debug code * Recursion

[Chris Angelico]
Or maybe "curry expressions!"... (I really hate that jargon too) I think this is a pretty ridiculous take on my argument. [Chris Angelico]
No. The lambda in lambda calculus was chosen arbitrarily. It has no deeper meaning. According to Dana Scott, who was a Ph. D student under Alonzo Church: The choice was "eeny, meeny, miny, moe" <https://www.youtube.com/watch?v=juXwu0Nqc3I&t=1m10s> [Chris Angelico]
Why isn't my example comparing the pseudo code: hand = sorted(cards, by=card.suit) to the actual code: hand = sorted(cards, key=lambda card: card.suit) suitable to at least demonstrate the basic idea? I can show you the noise right here: hand = sorted(cards, ke#=#############card.suit) I could come up with a hundred such examples if you need more "evidence" of my point, but I'm not interested in nit picking how one should properly represent or sort cards. I'm also not interested in discussing how I need to check my privilege because my proposal might not help Hellen Keller write better code. Maybe I should put you on the defensive and make you prove that it's always best to inject as much jargon as possible into Python and that there's no better form of lambda. We could be discussing this idea more deeply. Jonathan Fine pointed out some interesting ideas about this. But mostly you and D'Aprano seem interested in being contrarians and denying that there might be any hint of legitimacy to my point of view. I don't think it's unassailable, but it has nothing to do with the proper way to represent a wild-card in a poker simulation. [Chris Angelico]
it probably called it an "if-expression" or "conditional expression" or something.
I don't know how many times I have to reiterate this: I'm not talking about what humans call it. I'm talking about how it's expressed in code. [Chris Angelico]
What broad category of subjects?
* Functions as first-class objects * Callbacks & Event Handlers * Passing functions as arguments * the "semantics" as you put it In other-words, when you said: [Chris Angelico]
Whether you spell it "function(arg) {...}" or "lambda arg: ...", it's the semantics that are hardest to learn.
Those are orthogonal concerns! All else being equal, a descriptive name is better than a less descriptive alternative. It might not be on the same scale as the confusion caused by semantics, but it also doesn't have anything to do with the confusion caused by semantics. function.partial and function.given have the exact same semantics! We were literally only talking about names. Like I've said to D'Aprano: It may be way harder to drive a car than to buy windshield-wiper-solution for a car, but I can still prefer the name "windshield-wiper-solution" to "zeta" because calling it "zeta" just causes unnecessary confusion. Will it cause mass panic? Will it cause more car accidents? No. But, my goodness, you guys seem to want to talk a lot about that other stuff in order to convince me I'm wrong that "windshield-wiper-fluid" should not be called "zeta". I can't go two replies without you bringing it back up. It's really not worth the amount of words I've put into defending what I thought was a pretty reasonable POV. [Chris Angelico]
Okay! What's been your experience?
That students have trouble realizing that def f(x): return x*x is exactly the same as: f = lambda x: x*x yet have very little trouble learning how to write a function in JavaScript: f = function(x) { return x*x } Literally just that.

On Thu, Aug 23, 2018 at 11:59 AM, Abe Dillon <abedillon@gmail.com> wrote:
Because your form cannot possibly work without some additional information. How is "by=card.suit" supposed to ACTUALLY WORK? As soon as you make it work, you create extra noise all of your own - yaknow, like saying that "card" is a parameter to the function. So maybe it ain't just noise. I'm done arguing. You aren't listening. ChrisA

[Chris Angelico]
Because your form cannot possibly work without some additional information.
That isn't my form. That's PSEUDO CODE. Just like I wrote above it. You're the one who's not listening. The alternative I've suggested, for the thousanth time, is: hand = sorted(cards, by=card.suit with card) or hand = sorted(cards, by=card.suit with(card)) The noise compared to the PSEUDO CODE looks like this: hand = sorted(cards, by=card.suit ##########) Which, to me, is preferable to: hand = sorted(cards, ke#=#############card.suit) You need me to type that out a few dozen more times?

On 2018-08-23 03:10, Abe Dillon wrote:
You're complaining that it's "noise", but I think you need a bit of noise to tell you that it's defining a function, otherwise you'll see an expression and think it's evaluated immediately, but then you'll see the "with" at the end telling you "oh, by the way, this is a function, so don't evaluate it now". You gave an example in JavaScript and said that students had "very little trouble" with it, but notice how the function itself began with a reserved word. If you're complaining about the word "lambda", that's fine, but if you're complaining about where the arguments should go, then I'm afraid I'd have to say you're wrong.

Let me preface this by saying: I've already addressed the possibility of a form that tells you up-front that it's a function Granted it was 8 replies ago and at the end of a long-winded response, so I'll summarize here: A format like <PREFIX><EXPRESSION>[<SEPARATOR><SIGNATURE>] would, in my view, be preferable to a format that puts the signature first. An example might be: hand = sorted(cards, by=def card.suit with card) hand = sorted(cards, by=return card.suit from card) hand = sorted(cards, by=(:card.suit with card)) # the happiest form! hand = sorted(cards, by==>card.suit :: card) # eh... etc... There are many possibilities. [MRAB]
You're complaining that it's "noise", but I think you need a bit of noise to tell you that it's defining a function
I feel like the pseudo code example shows that at least isn't *always* true. Yes, the noise is neccessary for the computer's sake, but it doesn't have to go in-front of the logic. It's usually not that important for the reader. The intent is to sort cards by suit, not to declare a function that gets the suit of a card. The fact that you have to declare a function is secondary to the intent. If it were up to me, I'd make "by" the keyword for a key-function in sorted, sort, min, max, etc. and have special secondary keywords for simple, common cases:
[MRAB]
That's true of most expressions:
Assuming you know that grades.get is a method, you don't know that the expression passed to 'key' is a function until you read the whole expression. If you don't know what grades.get is, you don't know what kind of object is being passed to key:
best_student = max(spam, key=spam.eggs)
Is it catastrophic that you don't know what ham.eggs is? Is it something to do with card.suit with card being a literal that makes you demand to know what type of thing is being passed before you finish reading the expression? Because that clearly isn't true in the case of variables. Besides; you usually have several context clues leading up to the 'with' : 1) The function (if you're familiar with it) 2) The name of the function (if it's well named and you are familiar with the name) e.g. add_callback, add_handler, on_mouseover, etc.. 3) The name of a keyword parameter (if it's well named and you're familiar with the name) e.g. key, callback, handler, event_handler, filter, etc... 4) The usage of a variable that has yet to be declared (just like in generator/comprehension expressions) example: def best_hand(cards): hand = sorted(cards, key=card.suit with card) ... My hunch is that the vast majority of cases satisfy enough of those that reading a 'with' would rarely be all that surprising. I also assert that some of those conditions are far more critical to comprehending code, so if they're missing, your comprehension ends long before you're "surprised" by the appearance of a 'with'. All of the arguments in the following are clearly declared literals: foo = bar.baz(100, True, ham="spam") Can you read that? In a sense, yes. Can you comprehend it? No! What if I asked you "where's the bug?". Nope. Another example (from D'Aprano): sm = difflib.SequenceMatcher(isjunk=True) t = threading.Thread(target="hello") Now imagine that none of the 4 context clues above are true. Can you read those? Can you see the bugs? Is there even a point to reading beyond where your comprehension stops? If you don't know anything about what's expected for "target" or "isjunk" than reading any further isn't helpful. Knowing that "hello" is a string right away saves you no pain. The paramount problem is that you don't know that it's supposed to be a function. You need to stop when you loose comprehension and read the docs. Then when you come back, you'll know that 'isjunk' should be a function. The counter that there may be cases where none of the 4 context clues above exist indicates a more urgent problem than knowing the types of literals being passed (immediately or otherwise). Also, by the time you hit the "with" it's not like the "new information" requires you to look back and re-examine anything. It's just new information like any other compound statement:
[MRAB]
Yes, that was the context of the discussion I was referencing. Just the word "lambda". In this ongoing discussion I've declared on two separate gripes: 1) the word itself and 2) the format. I think a different format opens up other possible word choices, but that's not really important.

Chris Angelico wrote:
Yes, except that lambda is an even more arbitrary choice of letter -- as far as I know, it doesn't stand for anything. The story goes that, in his handwritten notes, Church used something like a caret or circumflex. When his work was published, the typesetter either misread it as a lambda or subsituted a lambda because it was the closest thing he had in his font, and from there on it stuck.
If we wanted to be true to the original we should call them "caret expressions" and write ^(x, y): x + y Nice and quiet! -- Greg

On Thu, Aug 23, 2018 at 05:55:13PM +1200, Greg Ewing wrote:
If you go back far enough, pretty much all words and written symbols are arbitrary. The word "dict" can be traced back to the Latin for "to say". Where did the Romans get their "dico" from? Linguists have extrapolated back to the hypothesised Proto-Indo-European word déyḱti (“to show, point out”). At this point, we can't even begin to guess where that word came from, but we can be sure that at some stage of human pre-history, it began as an arbitrary set of sounds. Many thousands of years later, it now means a hash table in Python. The only difference between dict and lambda is time. Lambda's arbitrariness is less than a century ago, while dict's is lost in the mists of prehistory. Why should that make a difference to anyone but a linguist? As I posted earlier, lambda has become a standard term, used by boring, staid, non-functional languages like Java and C++. There's nothing function-like about "lambda", but there's nothing function-like about "function" either. -- Steve

[Steven D'Aprano]
If you go back far enough, pretty much all words and written symbols are arbitrary.
I think this is wandering into nihilistic pedantry. Go back or forward far enough (or zoom in or out far enough) and nothing means anything. When I first learned Python, I had never heard the word "tuple" but as soon as I saw it, it made sense to me. It comes from the latin suffix for adjectives relating to multiples of things: "-uple" It's been around long enough to make its way into many common words (triple, tuplet, multiple) and many languages. That context makes it easy to remember. My guess is: even if you've only learned basic English, you have a far greater chance of being able to remember the meaning "tuple" over "lambda". Possibly even if you've never learned English, your chances of being able to relate "tuple" to relevant concepts is higher than being able to anchor "lambda" to anything relevant. [Steven D'Aprano]
As I posted earlier, lambda has become a standard term
I would agree that it's become a known term among computer scientists and maybe even the majority of professional programmers, but: 1) There are several terms commonly used interchangeably for the same concept including 'anonymous function', 'function literal', even 'deferred expression' works in the context of Python because the implementation only allows for a single expression (or implicit return statement?). So I don't think it has been standardized in the sense that it's the one, agreed upon, term. 2) being known of, does not equate to being well known. I've heard of a "busy beaver", but I couldn't tell you off the top of my head what it is. Lay people have heard of and talk about DNA or genes or genetics, but if you ask them what a codon is, most people's faces will go blank. The jargon of genetics is known about only in vague terms. 3) You've provided documentation from several languages to show that the term is used, but have you compared that to the usage of other terms? 4) Sometimes standardized terms can still be warty. There are plenty of terms in Science and Engineering that have confused roots and confusing consequences, but are too ingrained to abandon. The term "Rare Earth Metals" was coined in the late 18th century even though many of the elements are quite plentiful. Anonymous function or function literal are actually descriptive. Why not back those horses? [Steven D'Aprano]
There's nothing function-like about "lambda", but there's nothing function-like about "function" either.
I'm not sure what you mean by that.

Steven D'Aprano wrote:
The only difference between dict and lambda is time.
Well, "more arbitrary" was perhaps a rather loose way of saying it. What I meant was that the chain of associations is shorter for "lambda" than for "s-expression", because the "s" refers to a word the reader is probably already familiar with, but "lambda" doesn't refer to anything pre-existing that's semantically related. Not that there's anything wrong with that -- mathematicians love to endlessly re-use the same rather small set of symbols, so sometimes they have to make a completely arbitrary choice. -- Greg

Abe Dillon wrote:
They still find it's better to use a red break light symbol with the aim of clearly communicating to non-experts.
The handbrake warning light on my dashboard has a symbol that represents a brake drum and a pair of brake shoes, and the word "BRAKE" written underneath it. That's a technical term and an implementation detail, right there in the user interface! (Never mind that the implentation detail isn't accurate, because the car actually has disc brakes...) -- Greg

On Thu, Aug 23, 2018 at 03:12:30PM +1200, Greg Ewing wrote:
Indeed. I wonder whether Abe drives, and if he does, whether he has read the owner's manual. They are typically *full* of jargon. Similarly for bulldozers. Here's a short instructional video: https://www.youtube.com/watch?v=p2mh6kUuedk Many of the controls are described in common terms (why would they need jargon terms for "forward", "reverse", "left", "right"?), but they also mention specialist jargon like "throttle" and "decelerator". A bulldozer has perhaps as many as a dozen critical functions: move forward, reverse, lift the blade, etc, which can only combine in a rather limited number of ways. The user-interface is designed for real-time manual operation. Programming languages have multiple dozen features, hundreds if you include Python's std lib, which combine in a near-infinite number of ways. Programming is a batch operation: while a bulldozer operator has to react on the spot, the programmer typical gets to think ahead, write some code, think some more, write a bit more, do some incremental tests, write some more code, do some research, write a bit more code, think some more etc in dozens or hundreds of iterations before actually running the code in production. I don't think its productive to compare programming to driving a bulldozer. A better analogy would be sound mixing: https://videohive.net/item/sound-mixer-2/2244660 https://www.soundonsound.com/sound-advice/glossary-technical-terms -- Steve

[Steven D'Aprano]
Indeed. I wonder whether Abe drives, and if he does, whether he has read the owner's manual. They are typically *full* of jargon.
Do you still not understand the difference between documentation and interface? You seem to not even acknowledge that there's a difference between how one talks about a tool and how one uses said tool. Typically, the main concern of someone making a complex tool like a bulldozed is that the interface is as clear, accessible, language agnostic, simple, and utilitarian as possible. The reverse noise is a simple beep, not a voice saying "throttle set to reverse position". You use levers and buttons typically labeled with symbols rather than words. There are reasons why designers favor symbols and indicator lights over technical jargon. It has nothing to do with kiddie design vs. professional tools. It has everything to do with favoring the most intuitive interface possible to get work done. I honestly don't know what to say anymore. You keep conflating the syntax of Python with documentation and human-to-human communication. It's incredible. I don't know how many times I need to point out the difference. Do you think python's conditional operator should be like this: z = ConditionalOperator(predicate: x==y?, affirmative: x*2, negative: None) ? What can I do to illustrate that there is, indeed, a difference between what people call something and how someone uses a tool? I'm at a loss for words. On Thu, Aug 23, 2018 at 12:21 AM Steven D'Aprano <steve@pearwood.info> wrote:

TL;DR - I accept that there've been a few cases where I could have chosen my words better, and consequently I've rubbed Abe the wrong way; sorry about that Abe, as I said earlier (and I meant it) I have no grudge against you. - The most important technical issue I wanted to get from my discussion with Abe has been solved, I now believe that I understand what harm he feels was caused by chosing the name "lambda" over some alternative. - Namely (if I have understood Abe correctly) its the lost opportunity to have a better name. - Which seems to me to be so slight a harm that I don't think it gives us any guidance at all as to whether "partial" or "given" would make a better name for this proposed feature. (So much drama for so little gain.) Even after all these years of seeing people over-react to minor perceived slights (whether real or not), I cannot believe how quickly this one has degenerated into antagonism and over-reaction, and over so little. It certainly has not been helped by people fanning the flames of argument by calling this a "toxic forum". We should assume good faith. Before flying off the handle and taking offense, we should assume misunderstanding (on either or both party), accidental poor choice of wording, or merely robust debate rather than malice. We ought to be careful about making assumptions about people's motives from their responses. Email is a notoriously bad medium for judging people's motivation. The rest that follows is detail, responding to a few specific points which I deem relevant but not essential. * * * On Sun, Aug 12, 2018 at 10:31:36PM -0500, Abe Dillon wrote:
I explained my position on lambda as fully as I care to in my response to Niel if you care to read it.
I did read it. Just because I didn't respond to it directly doesn't mean I didn't read it. You say you object to the name, but then suggest a change that is idependent of that name. You talked about the placement of the function signature, wanting to put the body of the lambda first, before the parameter list. That has nothing to do with the choice of name "lambda", which is what I thought you were objecting too as it was too jargony. Moving the parameter list to the end of the expression is idependent of the keyword "lambda".
Nobody has accused you of frothing at the mouth. You seem to be talking about "opportunity costs" in a sense. Its not so much that the name lambda does harm in and of itself, but that another choice could be *even better* and do *even more good*. Is that a reasonable description of your position?
My original post was agreeing with you. Supporting your own words. If you don't agree with my position that we should avoid jargon for jargon's sake,
And don't imagine for a second I'm not aware of the irony.
I meant exactly what I said. *Possibly* a less jargon name would be nicer. Or possibly not. I was opening the issue up for further discussion, not nailing my colours to the mast as champion for the idea.
What about my saying it all of a sudden makes it an "extreme overreaction"?
Now you're quoting me out of context. It was your claim that the name "lambda" does harm to Python that I described that way. In hindsight, I wish I had left off the adjective "extreme". [...]
Notice: I never said "real, significant, non-trivial harm" anywhere in this entire discussion.
In fairness, you did say "minor" harm, so I'll accept that my emphasis on real significant etc was questionable. I don't know where the boundary between minor and trivial lies and I think people can disagree on this point. So I'll accept that here I read more into your words than were actually there. Sorry about that. [...]
That's not what I wrote. There's a difference between these two positions: - needing to learn to read English words to use Python; - using Python is the only reason to learn English. I said the first, not the second.
Where it comes from is not really important. Words change and are co-opted in new contexts. "Lambda" is rapidly become a standard programming term, and language agnostic, e.g.: https://martinfowler.com/bliki/Lambda.html -- Steve

[Steven D'Aprano] > - I accept that there've been a few cases where I could have > chosen my words better, and consequently I've rubbed Abe > the wrong way; sorry about that Abe, as I said earlier (and > I meant it) I have no grudge against you. Thank you. I hold no grudge against you either. I'm sorry for all the drama. [Steven D'Aprano] > - The most important technical issue I wanted to get from my > discussion with Abe has been solved, I now believe that I > understand what harm he feels was caused by chosing the name > "lambda" over some alternative. > - Namely (if I have understood Abe correctly) its the lost > opportunity to have a better name. Yes. That's pretty much it. In hindsight, I should have realized that the word "harm" carries a much more sever context in the programming community given all the "X considered harmful" articles out there. [Steven D'Aprano] > - Which seems to me to be so slight a harm that I don't think > it gives us any guidance at all as to whether "partial" or > "given" would make a better name for this proposed feature. I consider jargon for jargon's sake to be a poor reason to choose one term over a much more common term, however; I don't consider all jargon equal. I think "anonymous function" is far more descriptive than "lambda". I think you're ultimately right, however; that this doesn't guide the decision of "partial" over "given" very much because "partial" is not all that obscure. "partial function application" is fairly clear and as you said, Python wouldn't be trying to create an association from scratch. [Steven D'Aprano] > It certainly has not been helped by people fanning the flames of > argument by calling this a "toxic forum". At that point I felt like I had expressed that you came off as antagonistic toward me, had my feelings brushed off, then had multiple people ganging up on me about something I thought I had clearly articulated. I don't want to start a big fuss about it, but now both you and Stephen Turnbull have not-so-subtly referred to me indirectly like this. This time is fairly benign, but Turnbull's remark comes off as a passive-aggressive way of calling me toxic. I hope this isn't a sign of things to come where it's fine to passive-aggressively sling mud, but being direct is considered "crossing the line", because I find passive aggression far more insulting. I'm not an eight-year-old and people hiding behind the plausible deniability that even thinly veiled passive aggression affords them frustrates me. As I said early on: I'd rather resolve issues than have them continue to fester. Passive aggression does the exact opposite. [Steven D'Aprano] > We should assume good faith. Before flying off the handle and taking > offense, we should assume misunderstanding (on either or both party), > accidental poor choice of wording, or merely robust debate rather than > malice. We ought to be careful about making assumptions about people's > motives from their responses. Email is a notoriously bad medium for > judging people's motivation. > The rest that follows is detail, responding to a few specific points > which I deem relevant but not essential. Those are wise words and I'll try to adhere to them in the future. I would like to amend, that when someone signals that they feel like you're being aggressive towards them, it's a good idea to apologize. It's a simple act that can diffuse a lot of tension. [Steven D'Aprano] > > I explained my position on lambda as fully as I care to in my response to > > Niel if you care to read it. > I did read it. Just because I didn't respond to it directly doesn't mean > I didn't read it. I didn't mean that as an accusation that you hadn't read it. I'm sorry it came off that way. [Steven D'Aprano] > You say you object to the name, but then suggest a change that is > idependent of that name. Yes, I can see how that could lead to confusion. I'm sorry. I do, indeed, have two mostly separate objections to 'lambda': 1) I think it's a bad name 2) I think it's a sub-optimal form The only relevance of the form is that it sort-of illustrates a broader name-space to explore. For instance, the alternative name 'def' doesn't really make sense in the reversed order: hand = sorted(cards, key=def card: card.suit) # this kinda works, at least I think it's better than 'lambda' hand = sorted(cards, key=(card.suit def card) # this is... not as good [Steven D'Aprano] > > [Steven D'Aprano] > > > > > How can we insist that 3/4 of the world learn English words to use > Python > > > > Do you really think that 3/4 of the world learns English just to write > > Python? > That's not what I wrote. There's a difference between these two > positions: > - needing to learn to read English words to use Python; > - using Python is the only reason to learn English. > I said the first, not the second. I don't mean to come off as combative, but that is a direct quote, and I didn't try to take it out of context. If I did take it out of context, then I'm sorry. My point was that (and I may be wrong about this) I don't imagine most non-english speakers who want to write Python learning just enough English to write python. I imagine that most of them learn a broader vocabulary and thus, discussions about common English words still apply to them. It would be interesting to know either way, so maybe we should have a poll? I don't know.

Hello, Currently the user defined functions are mutables, there can be existed python codes like this:
Adding a new method to function object can break existing projects, but it is without impact with buit-in functions because they are immutables. 2018-08-09 18:59 GMT+02:00 Michel Desmoulin <desmoulinmichel@gmail.com>:

Le sam. 11 août 2018 à 10:34, Vincent Maillol <vincent.maillol@gmail.com> a écrit :
Or use a decorator like in the lib ? from funcoperators import partially @partially def f(x, y): return x-y g = f.part(4) g(5) The mutability solution however cannot have a "self" argument : def f(x,y): return x-y f.stuff = lambda self: self(5, 2) f.stuff() # missing self One would have to give "f". f.partial = lambda *a, **b: functools.partial(f, *a, **b) g = f.partial(4) g(5)

Therefore one can do a decorator that gives .partial: def partialize(f): from functools import partial f.partial = lambda *a, **b: partial(f, *a, **b) return f @partialize def f(x,y): return x-y g = f.partial(5) g(3) That's the same idea as funcoperators.partially but doesn't return a new function (which has the advantage of keeping help(f)) Le sam. 11 août 2018 à 14:53, Robert Vanden Eynde <robertve92@gmail.com> a écrit :

Michel Desmoulin schrieb am 09.08.2018 um 18:59:
Except that this only works for functions, not for other callables. Meaning, code that uses this for anything but its self-defined functions will break as soon as someone passes in a callable object that is not a function. Stefan

On Mon, Aug 13, 2018 at 07:46:49PM +0200, Stefan Behnel wrote:
That's an excellent point. If it were important to cover those use-cases, we could add a partial method to types, methods, builtin-functions etc. But I suspect that doing that would increase the cost of this proposed feature past the point where it is worthwhile. Do we often call functools.partial on arbitrary callable objects that we don't know in advance? (Not a rhetorical question.) I know I don't -- all the times I've called partial, I've known what the callable was, and it was always a function I created with def. But maybe others do something differently. I don't mind writing this: # only a minor inconvenience spam = func.partial(arg) eggs = functools.partial(callable, arg) given that I knew upfront that func was a function and callable was not. But if I didn't know, the utility of a partial method would be hugely reduced, and I'd just use functools.partial for everything. -- Steve

Do we often call functools.partial on arbitrary callable objects that we don't know in advance?
For my part, I don’t think I’ve ever used partial in production code. It just seems easier to simply fo it by hand with a closure ( Am I using that term right? I still don’t quite get the terminology) And if I had a callable class instance I wanted to “customize”, I’d likely use an OO approach — parameterize the instance, or subclass. So yeah, partial is probably used primarily with “regular” functions. But then, I don’t know that we need any easier syntax anyway — maybe I’d be more likely to use it, but it kind of feels like a feature that’s there so we can write more functional code for the sake of writing more functional code. If someone’s really interested in this, a search on gitHub or something to see how it’s used in the wild could be enlightening. -CHB
participants (30)
-
Abdur-Rahmaan Janhangeer
-
Abe Dillon
-
Alex Walters
-
Alexandre Brault
-
Antoine Pitrou
-
Bruce Leban
-
Chris Angelico
-
Chris Barker - NOAA Federal
-
Dan Sommers
-
Danilo J. S. Bellini
-
David Mertz
-
Greg Ewing
-
Jacco van Dorp
-
Jonathan Fine
-
Julien Palard
-
Michael Selik
-
Michel Desmoulin
-
MRAB
-
Neil Girdhar
-
Nicholas Chammas
-
Paul Moore
-
Rhodri James
-
Robert Vanden Eynde
-
Ryan Gonzalez
-
Stefan Behnel
-
Stephan Houben
-
Stephen J. Turnbull
-
Steve Barnes
-
Steven D'Aprano
-
Vincent Maillol