
On Tue, Jun 29, 2021 at 8:29 PM Steven D'Aprano <steve@pearwood.info> wrote:
On Tue, Jun 29, 2021 at 07:27:11PM +1000, Chris Angelico wrote:
My point is that the *iteration* isn't any different - the *range* is what's different. A filtered range makes very good sense here. Hence, a disjoint range object (one capable of subtraction) would be an excellent solution to the OP's problem.
I don't think that the OP's problem is *specifically and only* to iterate over disjoint ranges. I think that was just an illustration of the concept.
I have no objection to having some sort of ordered integer disjoint ranges, but I don't think that will be sufficient for the OP.
[...]
"Process the URLs I want, duh!"
Well, that gets down to the question of what counts as a "sentence". You shouldn't cram everything onto a single line of code just because you can, just as you shouldn't write an English sentence ten pages long.
Ah, you've been reading Daniel Defoe too! *wink*
Or certain Reddit posts. Seriously guys, we don't have a shortage of punctuation, it's okay to use the stuff!
Remember that list comprehensions aren't about saving a line of code. We often split comprehensions over multiple lines to make them more readable. Comprehensions are about making an *expression*.
Yes. And sometimes the best way to write it is one line, other times the best way is two lines. It's a question of whether it's one thought or two.
I see no meaningful benefit to cramming a conditional test into the same line as a loop. Current syntax is fine.
for item in iterable: if condition: block
Putting the condition on the same line as the for doesn't make it an expression. In general, saving one line and one indent is too little benefit to make up for the cost of cramming more details into a single line.
Stop thinking in terms of "saving lines", because that's not the point. It's always possible to write things on more lines, more indents, and fewer details per line. In fact, you can use dis.dis() to show you a MUCH longer form of the same code. We don't write assembly code, not because we need to use fewer lines, but because higher level constructs *better express thoughts*. If you think in terms of "iterate over this, check this condition, do this if it's true", then the correct way to write it is the way you show: a for loop, an if statement, and the block of code. If you think in terms of "iterate over this subset and do this", then the correct way to write it is as a single iteration with a filter. Of course, sometimes we don't have the syntax that will let us write things the most elegant way possible. But that's why we're talking on python-ideas - we're discussing ways to make the language better, more expressive, more efficient, etc.
But I don't see a problem with filtered iteration. We currently have a very clunky way of spelling it ("for url in (x for x in iterable if cond):"),
You can write it that way if you want, but why make two loops when you need only one? Isn't that doing more work than necessary? Using an extra loop inside a generator comprehension just to get an if is, I think, an example of being so sharp you cut yourself.
Yes - that's the problem with the current way of spelling it. It's an entire additional loop, a lot of junk in the source code ("x for x" is utterly pointless here), and in current implementations, an entire layer of function call and generator. That's why filtered iteration with its own keyword *would* be of value. If you could simply write: for url in iterable if cond: then (a) it wouldn't have two layered loops, (b) it wouldn't pretend that you can attach an else clause to the if, (c) it clearly expresses the concept of "filtered iteration". Unfortunately, it also becomes annoyingly ambiguous with "for url in iterable if cond else otheriterable:", which is perfectly legal syntax (although I can't imagine many situations where you'd want that). That was resolved for comprehensions, so maybe that wouldn't even be a problem. My point is that filtered iteration is basically a change to the thing you're iterating over - it is NOT a change to the body of the loop. It belongs on the loop header. In some cases, like the OP's example, it could be done with an actual iterable; in other cases, less so; but it still belongs with the iterable. ChrisA