1

I'm trying to use Python 3.10 structural pattern matching in Python shell:

match a:
   case (2 - 1):

after entering the second line, it gives me the following error:

  File "<stdin>", line 2
    case (2 - 1):
              ^
SyntaxError: imaginary number required in complex literal

NOTE: I know there's no code to execute after the case, I'm doing this in the shell and it throws this error immediately.
ALSO, I'm aware that I can store them as per this answer, but I'd rather do this directly if there is a way.

Tuor
  • 875
  • 1
  • 8
  • 32

2 Answers2

2

You're not allowed to compute arbitrary expressions in a pattern. There's just too much room for conflict with other pattern syntax.

For example, there's little point doing 2 - 1 as a pattern. If you had a value stored in a variable x, you might want to match against x - 1:

case x - 1:
    ...

but consider what case x means:

case x:
    ...

case x means "match anything and set x equal to the thing matched". It would be extremely confusing for case x and case x - 1 to do such extremely different things.

The error message you got is because there's one special case where addition and subtraction are allowed in a pattern, as part of a complex number "literal":

case 1+2j:
    ...

An expression like 1+2j or 1-2j is syntactically an addition or subtraction expression, not a single literal, so Python has to allow this specific case of addition or subtraction to allow constant patterns with complex constants. The error message comes from Python expecting the - to be part of a complex constant.

If you want to match against a computed value, use a guard:

case x if x == arbitrary_expression:
    ...
user2357112
  • 260,549
  • 28
  • 431
  • 505
1

You are treating the pattern after case as a normal expression with a value, but it is in fact an entirely new syntactical category in Python; it looks like object construction (i.e. some literal, or a call to a constructor), but it is in fact the opposite, a pattern is used to destructure the object you're trying to match.

So, this works:

match x:
    case 1:
        print('one')

Because the literal 1 means specifically an int with the value of 1. But (2 - 1) is an expression consisting of two literal integers, an operation and parentheses for grouping. Python tries to interpret it as a pattern and the pattern for destructuring a complex number comes closest.

For example:

n = 2 - 1j

match n:
    # these parentheses aren't needed, but allowed; 
    # they're here to show what Python thought you were trying to do
    case (2 - 1j):
        print('this number')
    case complex(real=r, imag=i):
        print('some other complex number')

As pointed out in the other answer, you can use a guard if you need to further restrict the value of what you're trying to match:

def try_this(n):
    match n:
        case int(x) if x == (2 - 1):
            print('what I want')
        case int(x):
            print('some other int')


try_this(1)
try_this(2)
Grismar
  • 27,561
  • 4
  • 31
  • 54