On Fri, 4 Mar 2022 at 02:48, Steven D'Aprano <st...@pearwood.info> wrote:
>
> On Thu, Mar 03, 2022 at 10:30:32PM +1100, Chris Angelico wrote:
> > On Thu, 3 Mar 2022 at 21:14, Steven D'Aprano <st...@pearwood.info> wrote:
> > > What did I say that made you think I denied the existence of filtered
> > > iteration? Was it the post where I pointed out we've been able to do
> > > filtered iteration going back to Python 1.x days?
> >
> > ANYTHING can be done by composing concepts. We don't need anything
> > more advanced than Brainf*. Why do we have better concepts? Because
> > they do a better job of expressing abstract concepts.
>
> They also do a better job of expressing *concrete* concepts, like
> addition.
>
> I believe this is a BF program to read two single digit numbers, add
> them, and print the result:
>
>     ,>,[<+>-]<------------------------------------------------.

This is a BF program that expresses an abstract concept of addition.

On what basis do you consider addition to be a concrete concept? Is
Python's idea of addition a single machine instruction? What, in your
view, makes one thing abstract and another thing concrete?

I put it to you that "add two numbers" is an abstract concept. Even
more so, "add two things" is definitely an abstract concept, and we
have a clean way of expressing this, regardless of whether it's string
concatenation, list extension, or numeric arithmetic. The BF program
you show clearly demonstrates that there are concrete actions that BF
is capable of, and they can be composed into the abstract idea of
integer addition. Composition can do anything! Why do we need better
languages? Because they are better able to express abstract concepts
like "add two integers".

Calling addition "concrete" because it has a simple spelling *in
Python* is the Blub Paradox at its best. You are denying features that
don't exist because composition can create them, and dismissing the
exact same argument about features that do exist, simply because...
they do exist. Addition is no more or less abstract than iteration, or
than filtered iteration, or than anything else. It's not a question of
"this is abstract, this is concrete". It's that pretty much everything
we ever think about is an abstract concept, to be implemented by the
compiler/interpreter in its own concrete way. The real question is:
Which abstract concepts deserve syntax?

(In fact, even BF's fundamentals could be considered abstract
concepts. But doing so would require that you be willing to consider
"concrete" to be the level of electrical engineering. Or domino
engineering. A half-adder can be implemented using a few square meters
of racing dominoes, and once you design that abstract concept, you can
build a four-bit adder with a full room of dominoes. When you think on
THAT scale, even a simple 'or' gate is a very abstract concept!!)

> I don't think that the difference between the status quo and the proposal:
>
>     # status quo for a filtered loop
>     for item in items:
>         if condition:
>             block
>
>     # proposal for a filtered loop
>     for item in items if condition:
>         block
>
> is comparable to the difference between BF and Python. How about you?

There is a difference of degree, to be sure. But in the status quo,
the programmer has to put the condition into the body, since there's
no way to express it in the header.

A for loop can be implemented more concretely using a while loop and
iter/next. We don't work that way. Why? Because it doesn't adequately
express the *concept* that we're trying to get across.

Programming is about expressing the ideas that we programmers have, in
ways that other programmers AND a computer will be able to understand.
Please can you stop blub-paradoxing yourself by assuming that what
exists is completely different from what doesn't exist?

> > > To be clear, there are lots of concepts in coding. Not all of them
> > > require their own specialised syntax. We don't have specialised syntax
> > > for a try...except block inside a loop, we use composition by putting a
> > > try...except block inside a for loop.
> > >
> > > Composition of statements is not a bug to be fixed.
> >
> > Indeed, but I'm putting the viewpoint - which a number of other people
> > have also put - that filtered iteration DOES deserve a better way of
> > expressing it.
>
> Better than the three or four ways we already have? Okay.
>
> To me, comprehensions were a significant improvement over the Python 1.x
> status quo, because they permitted us to write list builders as
> expressions, which could then be embedded directly in statements or
> other expressions without needing temporary variables.
>
> Generators and iterators were significant improvements, because they
> allow us to do things we couldn't do (easily, or at all) before.
>
> Context managers were another significant improvement.
>
> Aside from saving one line and one indent level, what *significant*
> improvement does the proposed change give us? This is not a rhetorical
> question.

Once again, you keep on focusing on "one line and one indent level".
It's not about that. I don't know how many more ways I can word this,
but *filtered iteration is an abstract concept that is very useful to
express*. Stop arguing against the strawman of the indentation level,
because I have never ONCE argued that I want to save lines, I have
never ONCE argued that I want to save indentation levels. Please. Drop
that tired line of argument.

> > > Nobody said that the idea of filtered looping doesn't make sense.
> > > They're only questioning whether it needs its own syntax instead of
> > > composing existing syntax.
> >
> > Yes. And it keeps coming up, so I think you should probably
> > acknowledge the fact that maybe, just maybe, this is more significant
> > than "one newline".
>
> I have repeatedly said that it also saves an indent level. I never
> bothered to mention the saving of one colon, because I thought that even
> for Python-Ideas that would be too trivially unimportant to mention.

And I never argued that it's worth saving the colon either, so you're
still arguing against something that isn't the point.

> What else does it give us? The one-line proposal and the two line status
> quo express exactly the same concept: a loop with a filter.

The two-line version is a loop, followed by a check, followed by
skipping the rest of the loop body. The proposal is a loop over part
of a list.

This is not the same thing.

> The functional programming idiom using filter() is even better at
> expressing that concept, at least for the case where the predicate is a
> function, but many people have an unfortunate aversion to f.p. idioms
> and so won't use it.

Yes, so where there predicate IS a function, great! But the versions
where it's not a function are much uglier. There are several, on an
ugliness spectrum, and the ones that aren't quite as ugly tend to be
quite inefficient to run, so people will tend to shy away from them. I
wouldn't mind that if they were really beautiful, but they aren't
beautiful enough to ignore performance completely.

> > > > You're thinking FAR FAR too concretely about this. It's not about
> > > > newlines.
> > >
> > > Of course it is. The whole point of the proposal is to move a two line
> > > statement into a single line. Earlier in this thread, I pointed out that
> > > this proposal adds no new functionality to Python. It doesn't allow us
> > > to do anything we can't already do, or even make it easier to do it.
> > >
> > > Literally all it saves is a newline and an indent.
> >
> > No, it is not. It is expressing the concept of filtered iteration.
>
> Which the existing idioms already do. So we have three or four ways of
> expressing filtered iteration, and the proposal is for another way of
> expressing filtered iteration which differs in that it saves a line and
> an indent level, and let's not forget that vitally important colon.
>
> Is there any other difference that I have missed?

Filtered iteration is not "loop over everything, then inside the loop
body, do a check, and possibly skip the rest of the body".

Filtered iteration is "loop over some of the list".

> > Do you, or don't you, accept that that is a concept? One moment you say
> > that it is a concept but you think it shouldn't get dedicated syntax,
>
> Yes. Many concepts don't have dedicated syntax.
>
> We don't have dedicated syntax for, say, recursion. (We just use a
> function call.) Or for getting the length of a sequence (another
> function call). Or sorting.
>
> > then the next, you imply that it isn't even a concept,
>
> Citation required.

You're arguing that it is exactly the same as the composition of
multiple statements.

> > and all we're
> > doing is reformatting code. That is simply not the case.
>
> Okay, now we're getting somewhere! So there is a semantic difference
> between the status quo and the new proposal. I'm sorry, I missed that!
> Mea culpa. Please take pity on me and explain what I have missed.
>
> In the status quo, we have a filtered loop written as:
>
>     for item in items:
>         if condition:
>             block
>
> but of course you know that already :-)
>
> So how does the proposal differ?
>
>     for item in items if condition:
>         block
>
> means what, if it isn't merely a reformatting of the status quo?

Well, if "a + b" is just a reformatting of the BF code you posted,
then yes, it's merely reformatting.

> > > > It's about expressing programmer concepts.
> > >
> > > Right. And composing a for-loop with a if statement expresses that
> > > concept perfectly. As does filter().
> >
> > No, it doesn't.
>
> Wait, you are saying that
>
>     for item in filter(predicate, items)
>
> *doesn't* express the concept of a loop with a filter?
>
> Then what does it express?

This does. The trouble is that it ONLY expresses that cleanly in the
case where the predicate is already a function. Otherwise it gets
cluttered with the mess of lambda functions, and it's a lot less
clear.

> And what do you say to the poster who wrote about "filtered iteration":
>
> [quote]
> ... you have this option:
>
> for thing in filter(isinteresting, stuff):
>
> which actually looks good. I think this is a pretty clear indication
> that the idea [filtered iteration] makes sense: functional programming
> languages have an idiom that aligns perfectly with it
> [/quote]
>
> The author of that post certainly sounds like he thinks that the f.p.
> idiom `for item in filter(...)` expresses filtered iteration "perfectly".
>
> (At least for the case where the predicate is a function. I don't think
> he is too fond of lambdas.)

Exactly. Try the versions where that isn't the case, and you'll see why.

We have [x + 1 for x in stuff if x % 3] without lambda functions. We
could have just used [x + 1 for x in filter(lambda x: x % 3, stuff)]
but that's just ugly. There is a huge difference between filter() with
an existing, and usefully-named, predicate, and filter() with a lambda
function (or worse, a single-use global function whose entire purpose
is that filtration).

Lambda functions are extremely useful when they're needed. They are
NOT arbitrary expressions that can be inserted anywhere.

Blub Paradox has you thoroughly in its grip.

ChrisA
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/SRW66ZR6PGSLHVROJHY6C3GR6KOIL2YF/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to