more readable "if" for multiple "in" condition
Hi I think the following syntax's: if foo in foobar or bar in foobar or baz in foobar: pass if foo in foobar and bar in foobar and baz in foobar: pass can be more readable and shorter if written as: if foo or bar or baz in foobar: pass if foo and bar and baz in foobar: pass maybe for "is" instead of: if foobar is foo or foobar is bar or foobar is baz: pass if foobar is foo or bar or baz: pass now the recommended syntax translate to this: (I think so) if foo (IS NOT '0' or None or empty) or bar (IS NOT '0' or None or empty) or baz in foobar so probably we must introduce a new type of 'or' (I recommend the CAPITAL "OR","AND") so this: if foo OR bar OR baz in foobar: pass translates to this: if foo in foobar or bar in foobar or baz in foobar: pass
On Wed, Jan 1, 2020 at 12:50 AM <iman.h.a.khamse@gmail.com> wrote:
Hi I think the following syntax's:
if foo in foobar or bar in foobar or baz in foobar: pass if foo in foobar and bar in foobar and baz in foobar: pass
can be more readable and shorter if written as:
if foo or bar or baz in foobar: pass if foo and bar and baz in foobar: pass
maybe for "is" instead of:
if foobar is foo or foobar is bar or foobar is baz: pass
if foobar is foo or bar or baz: pass
now the recommended syntax translate to this: (I think so)
if foo (IS NOT '0' or None or empty) or bar (IS NOT '0' or None or empty) or baz in foobar
so probably we must introduce a new type of 'or' (I recommend the CAPITAL "OR","AND") so this:
if foo OR bar OR baz in foobar: pass
translates to this:
if foo in foobar or bar in foobar or baz in foobar: pass
If you're testing if any of several things is in a collection, you probably should consider set intersection instead :) if {foo, bar, baz} & foobar: pass ChrisA
I can understand current way is little redundancy. But making new Keyword OR, AND or something like that is not kind to beginners. I don't think this proposal follows the zen of Python. However, I think what you want to say is nice. So, I propose this way. if (1, 2, 3) or in [1, 4, 5]: code if {"1", "2", "3"} and in "2020": code I don't think this is perfect suggestion. But I'm happy if I can write in this(or something like this) way. And to ChrisA. If one of the elements were instance of list(or unhashable type), that won't work. like below. class OR: def __init__(self, *args): self.data = args def in_(self, other): return any((x in other for x in self.data)) print({[1], [2], [3]} & [[1], [3]]) # invalid print(OR([1], [2], [3]).in_([[1], [3]])) # valid thank you. 2019/12/31 15:20、iman.h.a.khamse@gmail.comのメール:
Hi I think the following syntax's:
if foo in foobar or bar in foobar or baz in foobar: pass if foo in foobar and bar in foobar and baz in foobar: pass
can be more readable and shorter if written as:
if foo or bar or baz in foobar: pass if foo and bar and baz in foobar: pass
maybe for "is" instead of:
if foobar is foo or foobar is bar or foobar is baz: pass
if foobar is foo or bar or baz: pass
now the recommended syntax translate to this: (I think so)
if foo (IS NOT '0' or None or empty) or bar (IS NOT '0' or None or empty) or baz in foobar
so probably we must introduce a new type of 'or' (I recommend the CAPITAL "OR","AND") so this:
if foo OR bar OR baz in foobar: pass
translates to this:
if foo in foobar or bar in foobar or baz in foobar: pass _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/5UY57M... Code of Conduct: http://python.org/psf/codeofconduct/
On Dec 31, 2019, at 07:30, 永田大和 <chickenwingswillfly@gmail.com> wrote:
However, I think what you want to say is nice. So, I propose this way.
if (1, 2, 3) or in [1, 4, 5]: code
Even knowing what you want this to mean, I have a very hard time reading it as meaning that. To me, if `a or in b` means anything, it has to be something like asking whether a is either truthy, or in b. Meanwhile, in your reply to Chris’s suggestion to just use set operators:
If one of the elements were instance of list(or unhashable type), that won't work.
That’s true (although you actually used a set in one of your own two examples, which implies that this isn’t usually a problem, only occasionally). But you could solve that with a different type that provides the set operators. If you have values that are orderable, you can use a sorted set type (plenty of them available on PyPI). If not, you can write a simple trivial type that implements the set operators (in O(N*M) time—which sounds bad, but given that M is already 1 for this idiom, it’s fine). class TupleSet(tuple): def __and__(self, other): return type(self)(value for value in self if value in other) And now: if TupleSet((foo, bar, baz)) & foobar: It doesn’t look quite as nice as: if {foo, bar, baz) & foobar: … but on the rare occasions where you have a type that’s neither hashable nor orderable, it works. The real problem is that the set operators don’t cover all possible uses of the OP’s proposal. You can check whether any of the values are in foobar this way, and you can check if any are equal to foobar by just using & {foobar} in place of & foobar. But for other operators like > or in, there’s no way to translate that repeated check to a set operation.
31.12.19 08:20, iman.h.a.khamse@gmail.com пише:
Hi I think the following syntax's:
if foo in foobar or bar in foobar or baz in foobar: pass if foo in foobar and bar in foobar and baz in foobar: pass
can be more readable and shorter if written as:
if foo or bar or baz in foobar: pass if foo and bar and baz in foobar: pass
maybe for "is" instead of:
if foobar is foo or foobar is bar or foobar is baz: 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. And be aware that despite such syntax looks more readable to you, it may look confusing and ambiguous to other programmers.
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
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 <steve@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.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 _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/LSO4FH... Code of Conduct: http://python.org/psf/codeofconduct/
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]]
The goal was to have simpler syntax not a harder one, even if this already works this can't be said simpler (I even personaly find that harder and way less eyes pleasent). If the goal is to have something that works actually the default is cleaner: if foo in foobar or bar in foobar or baz in foobar: Le mer. 1 janv. 2020 à 08:35, Steve Barnes <GadgetSteve@live.co.uk> a écrit :
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 <steve@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.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 _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/LSO4FH... Code of Conduct: http://python.org/psf/codeofconduct/ _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/4GLS6F... Code of Conduct: http://python.org/psf/codeofconduct/
On 12/31/19 1:20 AM, iman.h.a.khamse@gmail.com wrote:
Hi I think the following syntax's:
if foo in foobar or bar in foobar or baz in foobar: pass if foo in foobar and bar in foobar and baz in foobar: pass
can be more readable and shorter if written as:
if foo or bar or baz in foobar: pass if foo and bar and baz in foobar: pass
maybe for "is" instead of:
if foobar is foo or foobar is bar or foobar is baz: pass
if foobar is foo or bar or baz: pass
now the recommended syntax translate to this: (I think so)
if foo (IS NOT '0' or None or empty) or bar (IS NOT '0' or None or empty) or baz in foobar
so probably we must introduce a new type of 'or' (I recommend the CAPITAL "OR","AND") so this:
if foo OR bar OR baz in foobar: pass
translates to this:
if foo in foobar or bar in foobar or baz in foobar: pass
IF I were to change the syntax ( which I don't propose), I believe the construct like foo or bar or baz in foobar to give you issues parsing. An alternative which is, in my opinion, more readable would be if any(foo, bar, baz) in foobar (and the alternative if all(foo, bar, baz) in foobar). To do this any and all could make a specially tagged tupl which interacts with operators like 'in' in a special way where it applies each of its members and or/ands the results. It may even be possible to do this with the existing Python by defining a suitable class any and all with an appropriate constructor and implementing its own version of things like in. (not sure if we can override 'is') -- Richard Damon
For what its worth, I find the proposed syntax confusing and difficult to read. Conceptually it makes sense, but using existing set operations seems like a far more readable way to handle this case. On Tue, Dec 31, 2019 at 11:03 AM Richard Damon <Richard@damon-family.org> wrote:
On 12/31/19 1:20 AM, iman.h.a.khamse@gmail.com wrote:
Hi I think the following syntax's:
if foo in foobar or bar in foobar or baz in foobar: pass if foo in foobar and bar in foobar and baz in foobar: pass
can be more readable and shorter if written as:
if foo or bar or baz in foobar: pass if foo and bar and baz in foobar: pass
maybe for "is" instead of:
if foobar is foo or foobar is bar or foobar is baz: pass
if foobar is foo or bar or baz: pass
now the recommended syntax translate to this: (I think so)
if foo (IS NOT '0' or None or empty) or bar (IS NOT '0' or None or empty) or baz in foobar
so probably we must introduce a new type of 'or' (I recommend the CAPITAL "OR","AND") so this:
if foo OR bar OR baz in foobar: pass
translates to this:
if foo in foobar or bar in foobar or baz in foobar: pass
IF I were to change the syntax ( which I don't propose), I believe the construct like foo or bar or baz in foobar to give you issues parsing. An alternative which is, in my opinion, more readable would be if any(foo, bar, baz) in foobar (and the alternative if all(foo, bar, baz) in foobar). To do this any and all could make a specially tagged tupl which interacts with operators like 'in' in a special way where it applies each of its members and or/ands the results.
It may even be possible to do this with the existing Python by defining a suitable class any and all with an appropriate constructor and implementing its own version of things like in. (not sure if we can override 'is')
-- Richard Damon _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/VGN4PW... Code of Conduct: http://python.org/psf/codeofconduct/
-- -Jon
I completely agree. All the variations suggested are unreadable mish-mash. Set intersection exists already and it's completely clear. On Tue, Dec 31, 2019, 12:05 PM Jonathan Crall <erotemic@gmail.com> wrote:
For what its worth, I find the proposed syntax confusing and difficult to read. Conceptually it makes sense, but using existing set operations seems like a far more readable way to handle this case.
On Tue, Dec 31, 2019 at 11:03 AM Richard Damon <Richard@damon-family.org> wrote:
On 12/31/19 1:20 AM, iman.h.a.khamse@gmail.com wrote:
Hi I think the following syntax's:
if foo in foobar or bar in foobar or baz in foobar: pass if foo in foobar and bar in foobar and baz in foobar: pass
can be more readable and shorter if written as:
if foo or bar or baz in foobar: pass if foo and bar and baz in foobar: pass
maybe for "is" instead of:
if foobar is foo or foobar is bar or foobar is baz: pass
if foobar is foo or bar or baz: pass
now the recommended syntax translate to this: (I think so)
if foo (IS NOT '0' or None or empty) or bar (IS NOT '0' or None or empty) or baz in foobar
so probably we must introduce a new type of 'or' (I recommend the CAPITAL "OR","AND") so this:
if foo OR bar OR baz in foobar: pass
translates to this:
if foo in foobar or bar in foobar or baz in foobar: pass
IF I were to change the syntax ( which I don't propose), I believe the construct like foo or bar or baz in foobar to give you issues parsing. An alternative which is, in my opinion, more readable would be if any(foo, bar, baz) in foobar (and the alternative if all(foo, bar, baz) in foobar). To do this any and all could make a specially tagged tupl which interacts with operators like 'in' in a special way where it applies each of its members and or/ands the results.
It may even be possible to do this with the existing Python by defining a suitable class any and all with an appropriate constructor and implementing its own version of things like in. (not sure if we can override 'is')
-- Richard Damon _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/VGN4PW... Code of Conduct: http://python.org/psf/codeofconduct/
-- -Jon _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/OTKTGK... Code of Conduct: http://python.org/psf/codeofconduct/
On Dec 31, 2019, at 08:03, Richard Damon <Richard@damon-family.org> wrote:
IF I were to change the syntax ( which I don't propose), I believe the construct like foo or bar or baz in foobar to give you issues parsing. An alternative which is, in my opinion, more readable would be if any(foo, bar, baz) in foobar (and the alternative if all(foo, bar, baz) in foobar).
But any(foo, bar, baz) already has a meaning (and so does all), so this is already valid but with the wrong result. Giving the exact same code a second meaning is obviously ambiguous. And there doesn’t seem to be any obvious way that either the any function or the compiler could resolve that ambiguity without reading your mind. That’s really the same problem the OP’s proposal already has. If the proposed syntax were an error today it might be conceivable to give it a new meaning, but it already has a meaning, so giving it a second one makes it ambiguous. Notice that you can actually use any here, although it’s not quite as simple as you want: if any(thing in foobar for thing in (foo, bar, has)): Maybe looking for a way to shorten that generator expression is worth pursuing, but I can’t think of anything obvious that makes sense.
To do this any and all could make a specially tagged tupl which interacts with operators like 'in' in a special way where it applies each of its members and or/ands the results.
It may even be possible to do this with the existing Python by defining a suitable class any and all with an appropriate constructor and implementing its own version of things like in. (not sure if we can override 'is')
No, you can’t override is. And you can override in, but only from the container side, not the element side. Most other operators do have a “reversed” method (like __radd__ for overriding + from the left or just __gt__ for overriding < from the left), but even that will only fire if the right side doesn’t know how to handle the left side’s type or if the left side is an instance if a subclass of the right side’s type. And I don’t think you’d want these classes to be “magical” things that can override operators in a way that you couldn’t write yourself, so the only way to make this proposal work is to change the entire operator data model in a pretty drastic way.
On 12/31/19 12:49 PM, Andrew Barnert via Python-ideas wrote:
On Dec 31, 2019, at 08:03, Richard Damon <Richard@damon-family.org> wrote:
IF I were to change the syntax ( which I don't propose), I believe the construct like foo or bar or baz in foobar to give you issues parsing. An alternative which is, in my opinion, more readable would be if any(foo, bar, baz) in foobar (and the alternative if all(foo, bar, baz) in foobar). But any(foo, bar, baz) already has a meaning (and so does all), so this is already valid but with the wrong result. Giving the exact same code a second meaning is obviously ambiguous. And there doesn’t seem to be any obvious way that either the any function or the compiler could resolve that ambiguity without reading your mind. Yes, I forgot that any and all are already defined by Python. That’s really the same problem the OP’s proposal already has. If the proposed syntax were an error today it might be conceivable to give it a new meaning, but it already has a meaning, so giving it a second one makes it ambiguous.
Notice that you can actually use any here, although it’s not quite as simple as you want:
if any(thing in foobar for thing in (foo, bar, has)):
Maybe looking for a way to shorten that generator expression is worth pursuing, but I can’t think of anything obvious that makes sense.
maybe it could be if (foo, bar, baz) any in foobar: since that is (I believe currently an error), but I agree it isn't that great of a syntax. I suspect this is really a maybe 'nifty' solution looking for a real problem, as you show, the generator expression really is a clean way to do it, and not THAT verbose.
To do this any and all could make a specially tagged tupl which interacts with operators like 'in' in a special way where it applies each of its members and or/ands the results.
It may even be possible to do this with the existing Python by defining a suitable class any and all with an appropriate constructor and implementing its own version of things like in. (not sure if we can override 'is') No, you can’t override is. And you can override in, but only from the container side, not the element side. Most other operators do have a “reversed” method (like __radd__ for overriding + from the left or just __gt__ for overriding < from the left), but even that will only fire if the right side doesn’t know how to handle the left side’s type or if the left side is an instance if a subclass of the right side’s type.
And I don’t think you’d want these classes to be “magical” things that can override operators in a way that you couldn’t write yourself, so the only way to make this proposal work is to change the entire operator data model in a pretty drastic way.
Ok, so you can't implement this with Python as it is. -- Richard Damon
On 2019-12-31 17:49, Andrew Barnert via Python-ideas wrote:
On Dec 31, 2019, at 08:03, Richard Damon <Richard@damon-family.org> wrote:
IF I were to change the syntax ( which I don't propose), I believe the construct like foo or bar or baz in foobar to give you issues parsing. An alternative which is, in my opinion, more readable would be if any(foo, bar, baz) in foobar (and the alternative if all(foo, bar, baz) in foobar).
But any(foo, bar, baz) already has a meaning (and so does all), so this is already valid but with the wrong result. Giving the exact same code a second meaning is obviously ambiguous. And there doesn’t seem to be any obvious way that either the any function or the compiler could resolve that ambiguity without reading your mind.
That’s really the same problem the OP’s proposal already has. If the proposed syntax were an error today it might be conceivable to give it a new meaning, but it already has a meaning, so giving it a second one makes it ambiguous.
Notice that you can actually use any here, although it’s not quite as simple as you want:
if any(thing in foobar for thing in (foo, bar, has)):
Maybe looking for a way to shorten that generator expression is worth pursuing, but I can’t think of anything obvious that makes sense.
To do this any and all could make a specially tagged tupl which interacts with operators like 'in' in a special way where it applies each of its members and or/ands the results.
It may even be possible to do this with the existing Python by defining a suitable class any and all with an appropriate constructor and implementing its own version of things like in. (not sure if we can override 'is')
No, you can’t override is. And you can override in, but only from the container side, not the element side. Most other operators do have a “reversed” method (like __radd__ for overriding + from the left or just __gt__ for overriding < from the left), but even that will only fire if the right side doesn’t know how to handle the left side’s type or if the left side is an instance if a subclass of the right side’s type.
And I don’t think you’d want these classes to be “magical” things that can override operators in a way that you couldn’t write yourself, so the only way to make this proposal work is to change the entire operator data model in a pretty drastic way.
An alternative syntax might be: if any {foo, bar, baz} in foobar: and: if all {foo, bar, baz} in foobar: but I'm not sure how I feel about it... The problem with using sets is that the objects must be hashable.
On Dec 31, 2019, at 11:50, MRAB <python@mrabarnett.plus.com> wrote:
On 2019-12-31 17:49, Andrew Barnert via Python-ideas wrote:
On Dec 31, 2019, at 08:03, Richard Damon <Richard@damon-family.org> wrote: IF I were to change the syntax ( which I don't propose), I believe the construct like foo or bar or baz in foobar to give you issues parsing. An alternative which is, in my opinion, more readable would be if any(foo, bar, baz) in foobar (and the alternative if all(foo, bar, baz) in foobar). But any(foo, bar, baz) already has a meaning (and so does all), so this is already valid but with the wrong result. Giving the exact same code a second meaning is obviously ambiguous. And there doesn’t seem to be any obvious way that either the any function or the compiler could resolve that ambiguity without reading your mind. That’s really the same problem the OP’s proposal already has. If the proposed syntax were an error today it might be conceivable to give it a new meaning, but it already has a meaning, so giving it a second one makes it ambiguous. Notice that you can actually use any here, although it’s not quite as simple as you want: if any(thing in foobar for thing in (foo, bar, has)): Maybe looking for a way to shorten that generator expression is worth pursuing, but I can’t think of anything obvious that makes sense. To do this any and all could make a specially tagged tupl which interacts with operators like 'in' in a special way where it applies each of its members and or/ands the results. It may even be possible to do this with the existing Python by defining a suitable class any and all with an appropriate constructor and implementing its own version of things like in. (not sure if we can override 'is') No, you can’t override is. And you can override in, but only from the container side, not the element side. Most other operators do have a “reversed” method (like __radd__ for overriding + from the left or just __gt__ for overriding < from the left), but even that will only fire if the right side doesn’t know how to handle the left side’s type or if the left side is an instance if a subclass of the right side’s type. And I don’t think you’d want these classes to be “magical” things that can override operators in a way that you couldn’t write yourself, so the only way to make this proposal work is to change the entire operator data model in a pretty drastic way. An alternative syntax might be:
if any {foo, bar, baz} in foobar:
and:
if all {foo, bar, baz} in foobar:
but I'm not sure how I feel about it...
Is this some new calling-like syntax, where `any {foo, bar, baz}` actually calls something like `any.__braces__(foo, bar, baz)‘, and the all and any builtins are changed to classes that implement that new dunder? If so, that seems like a pretty major change for a small benefit. And it still wouldn’t solve the problem, because whatever object it returns can’t override __rcontains__ because there is no __rcontains__. Or are you making any and all into contextual keywords—in most places they’re just identifiers (which normally pick out the builtins at runtime) but in some special context they’re instead syntax that means something special? If so, what’s the context? It can’t be just “right after if”, because the functions appear right after if all the time. Maybe “when followed directly by a container display” could work without requiring unacceptable parser look ahead (and without being ambiguous with existing valid syntax)? But that seems even worse than most proposals for contextual keywords.
On 2019-12-31 20:26, Andrew Barnert wrote:
On Dec 31, 2019, at 11:50, MRAB <python@mrabarnett.plus.com> wrote:
On 2019-12-31 17:49, Andrew Barnert via Python-ideas wrote:
On Dec 31, 2019, at 08:03, Richard Damon <Richard@damon-family.org> wrote: IF I were to change the syntax ( which I don't propose), I believe the construct like foo or bar or baz in foobar to give you issues parsing. An alternative which is, in my opinion, more readable would be if any(foo, bar, baz) in foobar (and the alternative if all(foo, bar, baz) in foobar). But any(foo, bar, baz) already has a meaning (and so does all), so this is already valid but with the wrong result. Giving the exact same code a second meaning is obviously ambiguous. And there doesn’t seem to be any obvious way that either the any function or the compiler could resolve that ambiguity without reading your mind. That’s really the same problem the OP’s proposal already has. If the proposed syntax were an error today it might be conceivable to give it a new meaning, but it already has a meaning, so giving it a second one makes it ambiguous. Notice that you can actually use any here, although it’s not quite as simple as you want: if any(thing in foobar for thing in (foo, bar, has)): Maybe looking for a way to shorten that generator expression is worth pursuing, but I can’t think of anything obvious that makes sense. To do this any and all could make a specially tagged tupl which interacts with operators like 'in' in a special way where it applies each of its members and or/ands the results. It may even be possible to do this with the existing Python by defining a suitable class any and all with an appropriate constructor and implementing its own version of things like in. (not sure if we can override 'is') No, you can’t override is. And you can override in, but only from the container side, not the element side. Most other operators do have a “reversed” method (like __radd__ for overriding + from the left or just __gt__ for overriding < from the left), but even that will only fire if the right side doesn’t know how to handle the left side’s type or if the left side is an instance if a subclass of the right side’s type. And I don’t think you’d want these classes to be “magical” things that can override operators in a way that you couldn’t write yourself, so the only way to make this proposal work is to change the entire operator data model in a pretty drastic way. An alternative syntax might be:
if any {foo, bar, baz} in foobar:
and:
if all {foo, bar, baz} in foobar:
but I'm not sure how I feel about it...
Is this some new calling-like syntax, where `any {foo, bar, baz}` actually calls something like `any.__braces__(foo, bar, baz)‘, and the all and any builtins are changed to classes that implement that new dunder? If so, that seems like a pretty major change for a small benefit. And it still wouldn’t solve the problem, because whatever object it returns can’t override __rcontains__ because there is no __rcontains__.
Or are you making any and all into contextual keywords—in most places they’re just identifiers (which normally pick out the builtins at runtime) but in some special context they’re instead syntax that means something special? If so, what’s the context? It can’t be just “right after if”, because the functions appear right after if all the time. Maybe “when followed directly by a container display” could work without requiring unacceptable parser look ahead (and without being ambiguous with existing valid syntax)? But that seems even worse than most proposals for contextual keywords.
I was simply suggesting an alternative syntax to "any(foo, bar, baz)", which already has a meaning. The other questions - to how it would work - remain.
I might go with: (a, b, c) orin something And (a, b, c) andin something But really, not needed. -CHB On Tue, Dec 31, 2019 at 3:25 PM Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
if a or b or c is in x:
if a and b and c are in x:
-- Greg _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/KJSHAZ... Code of Conduct: http://python.org/psf/codeofconduct/
-- Christopher Barker, PhD Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython
On Dec 31, 2019, at 05:50, iman.h.a.khamse@gmail.com wrote:
if foo or bar or baz in foobar: pass if foo and bar and baz in foobar: pass
maybe for "is" instead of:
if foobar is foo or foobar is bar or foobar is baz: pass
if foobar is foo or bar or baz: pass
now the recommended syntax translate to this: (I think so)
if foo (IS NOT '0' or None or empty) or bar (IS NOT '0' or None or empty) or baz in foobar
I’m not sure what this translation is supposed to mean, since that isn’t valid Python syntax or meaningful English, but it does seem like you’re trying to say something that’s pretty close to what’s right. foo or bar or baz in foobar … is roughly … foo if foo else (bar if bar else (baz in foobar)) And that “if foo” is true for most types unless foo is False, None, an empty collection, or a numeric zero (but not the string '0'; that’s perfectly truthy). While this seems silly with meaningless names, the exact same syntax is often useful: if already_found or child.find(key) or key in known_bad_keys: Surely this has to mean that we’re checking whether a flag is true, or a find function finds something, or a key is a known bad key, not whether any of the flag, the value found by the function, or the key are known bad keys. And that’s exactly why this syntax is ambiguous not just to the parser, but to humans. In most cases the existing meaning makes sense. In some cases, your meaning makes sense. If there’s any overlap between the two sets of cases, both make sense, so it’s ambiguous. Even if you can find a way to reliably disambiguate, that’s still an extra concept that the reader has to think through to understand your code. At which point, even if it’s fewer characters than using a set operator where it makes sense, or a generator expression inside any otherwise, it’s still not more readable.
if foo OR bar OR baz in foobar: pass
Someone else noted, and I agreed, that set intersection is already the obvious way to do this. But yes, some things aren't hashable. So in concept you could make a custom type that had some set-like behaviors, and so on. But all of this is crazy work for a pattern that really isn't that common, in my experience. The obvious answer doesn't disrupt anything: just write a FUNCTION: if any_in((foo, bar, baz), foobar): ... That's completely obvious and needs no change. Heck, write all_in(), most_in(), and at_least_n_in(), while you are at it. None need syntax, all variations take 2-5 lines of code each, depending on implementation.
participants (15)
-
Andrew Barnert
-
Chris Angelico
-
Christopher Barker
-
David Mertz
-
Greg Ewing
-
iman.h.a.khamse@gmail.com
-
Jonathan Crall
-
Jorropo .
-
komissar.off.andrey@gmail.com
-
MRAB
-
Richard Damon
-
Serhiy Storchaka
-
Steve Barnes
-
Steven D'Aprano
-
永田大和