This could also be resolved with any &/or all i.e.:

    if any([foo in foobar, bar in foobar, baz in foobar]):

Or even:

    if any([l in foobar for l in [foo, bar, baz]])

but I would like to suggest allowing any & all to take more than a single 
argument,, i.e. if there are multiple arguments they are all tested for truth 
but if a single argument then it must be an iterable.

Steve Barnes

P.S. Happy  New Year & RIP Python 2.

-----Original Message-----
From: Steven D'Aprano <st...@pearwood.info> 
Sent: 01 January 2020 02:01
To: python-ideas@python.org
Subject: [Python-ideas] Re: more readable "if" for multiple "in" condition

On Tue, Dec 31, 2019 at 05:25:51PM +0200, Serhiy Storchaka wrote:

> 31.12.19 08:20, iman.h.a.kha...@gmail.com пише:

[...]
> >if foo or bar or baz in foobar:
> >     pass

[...]
> >if foobar is foo or bar or baz:
> >     pass

> This looks like an interesting idea for a completely new programming 
> language (together with "when" proposed as an alias of "if" in the 
> neighbor thread). Unfortunately it is not compatible with existing 
> Python syntax.

I agree with Serhiy that this is a very interesting idea, and that it is not 
compatible with existing Python syntax. As many others have already pointed 
out, the suggested syntax already has meaning.

If this were to work at all, it ought to work for all comparison operators, not 
just `in` and `is`.

Because so much of Python's grammer is very English-like, it is a very common 
newbie mistake to assume that conjunctions work the same way. I have seen 
newbies write code like this:

    spam and eggs in sandwich

expecting it to mean `spam in sandwich and eggs in sandwich`. And despite 20+ 
years of using Python, I still sometimes find myself typing

    spam or eggs is None

when I am thinking `spam is None or eggs is None`. So I think that this sort of 
English-like semantics would be a natural fit for Python. I just don't see a 
good way to retro-fit it into the language without breaking existing code.

I don't think that many English speakers will have trouble with the intent of 
such clauses as:

    if "Simon Pegg" and "Nick Frost" or "Dwayne Johnson" in movie.cast:
        go_see_movie()

The problem isn't that the syntax is unreadable but that it already has a 
meaning in Python, so there is an ambiguity that requires semantic 
understanding, not just syntax, to resolve. We can resolve it in the movie cast 
example, because it is something we'd say in English where the intent is clear. 
But other examples remain ambiguous:

    if func(arg)[1] and db[key] or obj.attr > expression

    # Does this mean...?
    (1)  (func(arg)[1] > expression) 
         and (db[key] > expression) 
         or (obj.attr > expression)

    (2)  func(arg)[1]
         and db[key]
         or (obj.attr > expression)

The first has the virtue that `expression` is only evaluated once, but the 
second is the existing meaning and we can't change that without breaking code.

So I fear that, no matter how newbie errors this would prevent, no matter how 
English-like it would be, and no matter that the suggested alternative helps 
DRY (Don't Repeat Yourself), we're stuck with the existing semantics of the 
syntax.

I would love to be proven wrong, but I don't think that there is any natural, 
English-like, backwards-compatible way to add this sort of "grouped/delayed 
conjunctions" into Python.

Adding additional keywords like OR and AND isn't very satisfactory, because 
newbies will continue to use the wrong keyword.

The solution I like the best would be if we had an additional kind of bracket, 
we could explicitly group the alternatives:

    if ¿"Simon Pegg" and "Nick Frost" or "Dwayne Johnson"? in movie.cast:
        go_see_movie()

I am not seriously proposing ¿ ? as bracketing characters, just using them as a 
placeholder.

But honestly, the benefit here is relatively small. Newbies will forget to use 
the ¿? brackets and get the wrong answer, and now with the walrus operator we 
can partially solve the DRY problem:

    if "Simon Pegg" in C:=movie.cast and "Nick Frost" in C or "Dwayne Johnson" 
in C:
        go_see_movie()

Often there are straight-forward alternatives:

    # ¿spam and eggs? is None
    spam is eggs is None  

or one can use the any() and all() builtins. So the overall benefit is moderate 
(not zero) and the difficulty in making it work is high (but probably not 
impossible).

[Aside: one of the oddities of English is that "conjunctions" are words which 
join phrases (and, or, but, if, as ...) but some conjunctions are conjunctions 
(and) while others are disjunctions (or).]


--
Steven
_______________________________________________
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/LSO4FHRTEMEYCALNL73HEN32R5SUMS6Y/
Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________
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/4GLS6FYHJLR3R62DAJNSGNJIOUXMRIG6/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to