On Sat, 5 Mar 2022 at 23:32, Paul Moore firstname.lastname@example.org wrote:
On Sat, 5 Mar 2022 at 12:12, Chris Angelico email@example.com wrote:
On Sat, 5 Mar 2022 at 22:22, Stephen J. Turnbull firstname.lastname@example.org wrote:
Python has one, and you've already mentioned it:
for thing in (x for x in this_collection if is_interesting(x)):
It's noticably verbose, but it's an exact translation of your statement of the abstract concept above. It has all the benefits of the proposed syntax except compactness.
It is extremely verbose, considering that the filtering part of a comprehension uses the same variable name as iteration, doesn't need anything to be repeated, and is just another clause. A simple representation of that in a statement loop would be "for thing in this_collection if is_interesting(thing):", which doesn't repeat itself at all (the variable name "thing" is kinda essential to the concept of filtration here, so I don't count that); and repetition isn't simply about number of characters on the line, it's about reducing the potential for errors. (Plus, the genexp adds a significant amount of run-time overhead.)
So you're right, I stand (partly) corrected: there IS a very clunky way to spell this concept.
What Python needs is a non-clunky way to express this.
for thing in filter(is_interesting, this_collection): ...
That seems pretty non-clunky. Is the issue here that "filter" is not sufficiently well-known? Or that you don't want to name the is_interesting function, and lambdas are "too clunky"? This feels like another case where the general dislike of lambda results in people wanting special-case syntax so they can avoid either writing a throwaway function, or using lambda.
The throwaway function is a *terrible* idea for a lot of situations, because it puts the condition completely out-of-line. You have to go dig elsewhere to find out the meaning of the filter. A lambda function can work, but is about as clunky as the genexp. Using filter() is only non-clunky in the specific situation where a function already exists to do the filtration, and in my personal experience, that's been quite rare.
If we had "placeholder" expressions (see, for example https://pypi.org/project/placeholder/) so we could do things like
from placeholder import _ for thing in filter(_%3==0, the_list): ...
would that be sufficiently "non-clunky"?
That is something I could get behind. I don't like the underscore, since that usually means "meaningless", and would have to be carefully managed to avoid shadowing; but that is definitely a possibility.
Does it work if you need to use the underscore twice? For instance, what if you want to find long-running jobs, where "_.end - _.start > 30" ?
(This also still has the performance cost of filter and a lambda function, which is a lot more than just having a bit of extra code as part of the loop. But that's less significant.)
There are many ways of achieving this sort of result. Clearly, from the fact that this request comes up repeatedly, there's *something* unsatisfying about all of them, but I'm not entirely clear what particular problem is uniquely solved by new "for x in collection if condition" syntax, and not by any of the other possibilities?
They are all clunky except in very specific circumstances, like "iterate over the non-empty elements" or something. They don't generalize well.
Personally, I don't mind having the if on a separate line, I find the generator expression tolerable but a bit verbose, and I'm glad "filter" and the placeholder library exist in case I need them, but I've never really found the existing options sufficiently annoying that I've wanted a for...if statement.
And clearly a number of other people DO mind having it on a separate line, because it's putting code in the body that belongs in the header.
However, as I found out by writing PEP 671, there are enough people who focus on the concrete that it's never going to happen. All you have to do is keep on arguing against straw-men and eventually people get weary of arguing the same unanswered arguments again and again.
The Blub Paradox is strong on this list.