Problem
I have recently converted a large project which heavily uses unions from if
chains to match
/case
. The project now has ~150 match
statements. Some cases have many possible values in the same branch, and see a lot of churn, so to keep diffs minimal and clean when a value is added or removed, I put each value in its own line with a trailing comma. Before match
I would have written e.g.
if color in (
Color.RED,
Color.BLUE,
):
return 'nice'
if isinstance(shape, (
Square,
Trapezoid,
):
return 4
and adding new values at the start or end produces a clean diff:
if color in (
Color.RED,
Color.BLUE,
+ Color.GREEN,
):
return 'nice'
if isinstance(shape, (
+ Kite,
Square,
Trapezoid,
):
return 4
With match
I now write it like this (using two different styles for demonstration purposes):
match color:
case (
Color.RED |
Color.BLUE
):
return 'nice'
match shape:
case (
Square
| Trapezoid
):
return 4
Besides it not being symmetric, the diffs are not as nice, touching unrelated lines:
match color:
case (
Color.RED |
- Color.BLUE
+ Color.BLUE |
+ Color.GREEN
):
return 'nice'
match shape:
case (
- Square
+ Kite
+ | Square
| Trapezoid
):
return 4
Proposed solution
Allow a leading |
in or-patterns, so can write like this:
match color:
case (
| Color.RED
| Color.BLUE
):
return 'nice'
match shape:
case (
| Square
| Trapezoid
):
return 4
and the diff:
case (
| Color.RED
| Color.BLUE
+ | Color.GREEN
):
return 'nice'
match shape:
case (
+ | Kite
| Square
| Trapezoid
):
In practical terms, it means altering the grammar like so:
diff --git a/Grammar/python.gram b/Grammar/python.gram
index 51f846a57f4..51e4174f1aa 100644
--- a/Grammar/python.gram
+++ b/Grammar/python.gram
@@ -470,7 +470,7 @@ as_pattern[pattern_ty]:
| invalid_as_pattern
or_pattern[pattern_ty]:
- | patterns[asdl_pattern_seq*]='|'.closed_pattern+ {
+ | '|'? patterns[asdl_pattern_seq*]='|'.closed_pattern+ {
asdl_seq_LEN(patterns) == 1 ? asdl_seq_GET(patterns, 0) : _PyAST_MatchOr(patterns, EXTRA) }
closed_pattern[pattern_ty] (memo):
TypeScript (in a type position) and other languages do this. Hopefully auto-formatters like black will format in this style (when the pattern is one-per-line).
Side note
BTW, there is a similar problem with multi-line unions â before:
Shape: TypeAlias = Union[
Kite,
Square,
Trapezoid,
]
After:
Shape: TypeAlias = (
Kite
| Square
| Trapezoid
)
But this is not the same part of the grammar and I am not proposing any changes for it in this proposal.