Open gvanrossum opened 4 years ago
This would be easy enough with an In(container)
object, or a guard. A perhaps more magical option could be to give range
a __match__
method with the same semantics.
I'm not a huge fan of using Ellipsis
like this, though. I think it works better for other languages that already have literal range constructs with the same syntax.
That's a neat solution. +1 (to either In(container)
or giving range()
a __match__
method).
Is using range() as a match expression ambiguous? Does range(3)
match 2
or (0, 1, 2)
?
In some regards a slice operator makes more sense as a matching expression, but I don't think that works syntactically.
I'm sure range(3)
matches (0, 1, 2)
-- when I evaluate list(range(3))
I get [0, 1, 2]
and basically everybody knows that.
Let me perhaps give another reason why case 1...6
might not bring quite as much as we would hope for. I actually loved this syntax in Pascal. But my main use case was typically character ranges, not integers (I still find syntax like case '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'
rather clumsy). However, since Python has no character type (only strings) in the first place, '0'...'9'
is simply not feasible, anyway.
Range checks of that form are probably better and quite adequately expressed through classic if
-elif
-chains, anyway.
Syntax like case 1...6
makes IMHO most sense if you have fast jump tables in mind, where the compiler can check that the entire (numerical) range is covered, and then quickly jump to a specific target based on its value. This is quite a different beast than the structural patterns we have in mind here, and should thus probably better be a non-goal.
Finally, case range(7)
seems to express something quite different than case 0...6
. With range(7)
I would expect the matching value either be a range
-object or the full sequence [0, 1, 2, .., 6]
. In the case of case 0...7
I would expect any number within that range to match, more along the lines of 0 <= x <= 7
.
Agreed -- unless there are strong objections, let's mark this one as "rejected".
Another reason against case 1...6
is that there would be endless debate/confusion about whether it represents a half-open interval (e.g. is it like range(1, 6)
or like range(1, 7)
), and what to do if the target is a float.
Speaking of floats, syntactically 1...6
would cause problems because the tokenizer would scan it it as 1. . .6
.
(However, I don't think that the character range arguments holds water -- we could always declare that it would have to be a string containing a single unicode character. We do this for ord()
for example -- another homage to Pascal. :-)
Yes, implementing range patterns with dedicated syntax is a waste. We can implement this with current protocol.
But we should not. I have seen your hack and think it is too obfuscated.
If you can support parameterised patterns in some way, it won't be obfuscated at all.
Some languages have range cases, so you could write e.g.
case 1...6: print("Dice")
. This seems tricky, and quite specialized. Let's not do this?