On Tue, Dec 31, 2019 at 05:25:51PM +0200, Serhiy Storchaka wrote:
31.12.19 08:20, iman.h.a.khamse@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