Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #69556 > unrolled thread
| Started by | Chris Angelico <rosuav@gmail.com> |
|---|---|
| First post | 2014-04-03 08:50 +1100 |
| Last post | 2014-04-03 00:50 -0600 |
| Articles | 3 — 3 participants |
Back to article view | Back to comp.lang.python
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: Yet Another Switch-Case Syntax Proposal Chris Angelico <rosuav@gmail.com> - 2014-04-03 08:50 +1100
Re: Yet Another Switch-Case Syntax Proposal Steven D'Aprano <steve@pearwood.info> - 2014-04-03 01:06 +0000
Re: Yet Another Switch-Case Syntax Proposal Ian Kelly <ian.g.kelly@gmail.com> - 2014-04-03 00:50 -0600
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-04-03 08:50 +1100 |
| Subject | Re: Yet Another Switch-Case Syntax Proposal |
| Message-ID | <mailman.8822.1396475455.18130.python-list@python.org> |
On Thu, Apr 3, 2014 at 1:53 AM, Lucas Malor <3kywjyds5d@snkmail.com> wrote:
> For example, in a "switch x" statement, the code "case iterable: " is identical to "if x in iterable: " (or elif etc). So if you want to perform the same case block for more than one value, you have only to specify a tuple, a range etc.
> I would suggest to add an exception for non-iterable variables, so that you don't have to write "case var, : " but simply "case var: " and it will be identical to "if x == var: ". It's a bit tricky but the alternative is ugly.
>
This is sounding like a nasty special case. I'm ambivalent on the
overall proposal (want to see some real-world usage examples and how
they read), but I don't like the "iterable vs non-iterable"
distinction. Compare:
case 1,2,3: # Tuple - checks for any of its members
case range(10,110,10): # Range object - beautiful, convenient!
case 42: # Non-iterable, works the way you'd expect
case {1:"Test",2:"Hello",3:[]}: # Dictionary, may be surprising
case "Test",: # Tuple with a single string in it - works but ugly
case "Test": # And there's your problem.
You now have three valid ways to interpret that last statement:
1) It matches the exact string "Test", the way people will expect
2) It matches any of the results of iterating over it
3) It matches anything where x in "Test" is true
The first option is a big fat special case, and one that'll get more
complicated as you start looking at subclasses and such. The second
means that "case x" is equivalent to "case tuple(x)", but I can't
imagine people would actually want that in real usage. The third is
the way you've described it so far, but again, I cannot imagine it as
anything other than highly surprising that my last statement above
will match "st" and "es".
It would be more invasive to the language, but possibly better, to
have a new magic method __case__ which gets called to see if this
object matches this switched object. If that isn't defined, an
equality check is done. Then all of the above cases can be made
unsurprising by simply defining __case__ on a tuple (membership test)
and a range (ditto, except that the members aren't specifically
instantiated); everything else will check equality. (Having a dict
check for its keys is surprising, IMO, and I don't mind that one not
working.) It'd make it a *lot* easier to ensure sane behaviour in
custom classes; if you want your class to function like a single unit,
don't define __case__, but if you want it to function like a
collection, set __case__=__in__. What do you reckon?
ChrisA
[toc] | [next] | [standalone]
| From | Steven D'Aprano <steve@pearwood.info> |
|---|---|
| Date | 2014-04-03 01:06 +0000 |
| Message-ID | <533cb3fd$0$2909$c3e8da3$76491128@news.astraweb.com> |
| In reply to | #69556 |
On Thu, 03 Apr 2014 08:50:47 +1100, Chris Angelico wrote:
> On Thu, Apr 3, 2014 at 1:53 AM, Lucas Malor <3kywjyds5d@snkmail.com>
> wrote:
>> For example, in a "switch x" statement, the code "case iterable: " is
>> identical to "if x in iterable: " (or elif etc). So if you want to
>> perform the same case block for more than one value, you have only to
>> specify a tuple, a range etc. I would suggest to add an exception for
>> non-iterable variables, so that you don't have to write "case var, : "
>> but simply "case var: " and it will be identical to "if x == var: ".
>> It's a bit tricky but the alternative is ugly.
>>
>>
> This is sounding like a nasty special case. I'm ambivalent on the
> overall proposal (want to see some real-world usage examples and how
> they read), but I don't like the "iterable vs non-iterable" distinction.
If we're going to add "switch" and "case" keywords, how about we also add
"of"? Then we can write:
switch x case of a, b, c:
# x equals one of a, b or c
case of d, e, f:
# x equals one of d, e or f
case in g, h, i:
# g, h and i must be iterable, and x is in one of them
else:
# none of the above match
That means we can cleanly match the common use-case where we want to
match something by equality, comparing against a list of 1 or more
(usually) scalar values:
case of 1, 2, [23, 42], 99:
assert x == 1 or x == 2 or x = [23,42] or x == 99
while also supporting the more complex case where we're matching against
one or more sequences:
case in (1, 2, 99), [23, 42]:
assert x == 1 or x == 2 or x = 99 or x == 23 or x == 42
Of course, in practice the second case is likely to be given dynamically,
not as literals:
case in LIST_OF_KEYWORDS:
...
Another option is to say that the cases being tested ought to be quite
small in number. If you're trying to do this:
case in range(100000000):
...
you're doing it wrong. That being the case, we only need to match by
equality:
case 1, 2, 3:
assert x == 1 or x == 2 or x == 3
and can write this when we want to match against a sequence or iterator:
case *LIST_OF_KEYWORDS:
...
and on the rare occasion we want to match against substrings, we can
build a wrapper class:
class Wrapper:
def __init__(self, value):
self.value = value
def __eq__(self, other):
return other in self.value
case Wrapper("Hello world!"):
# matches if x is a substring of "Hello world!"
But what's the advantage here? Since Python is not a static-typed
language, it's unlikely that there are any compile-time optimizations
that can be performed here. If there are any run-time optimizations that
a JIT optimizing compiler like Python can perform, it probably can
perform them just as well on a series of if...elif. So I'm not sure I see
what having special syntax for a switch-case statement gives us.
--
Steven
[toc] | [prev] | [next] | [standalone]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2014-04-03 00:50 -0600 |
| Message-ID | <mailman.8826.1396507894.18130.python-list@python.org> |
| In reply to | #69561 |
On Wed, Apr 2, 2014 at 7:06 PM, Steven D'Aprano <steve@pearwood.info> wrote: > If we're going to add "switch" and "case" keywords, how about we also add > "of"? Then we can write: > > switch x case of a, b, c: > # x equals one of a, b or c > case of d, e, f: > # x equals one of d, e or f > case in g, h, i: > # g, h and i must be iterable, and x is in one of them > else: > # none of the above match I don't think I like the idea of having "case in" and "case of" meaning two different things, particularly since the one that you have labeled with "of" is the one that I think should use "in" and vice versa. Seems like too much potential for confusion here.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web