2

PEP 622 introduced match statement as an alternative to if-elif-else. However, one thing I can't find in the proposal or in any of the material online is whether the match statement can be used as an expression and not just as a statement.

A couple of examples to make it clear:

Example 1:

def make_point_2d(pt):
    match pt:
        case (x, y):
            return Point2d(x, y)
        case _:
            raise TypeError("not a point we support")

Example 2:

match response.status:
    case 200:
        do_something(response.data)
    case 301 | 302:
        retry(response.location)

In the first example, the function returns from inside a case clause, and in the second example, nothing is returned. But I want to be able to do something like the following hypothetical example:

spouse = match name:
    case "John":
        "Jane"
    case "David":
        "Alice"
print(spouse)

But it doesn't compile.

Abhijit Sarkar
  • 21,927
  • 20
  • 110
  • 219
  • 7
    Well, it’s called a `match` *statement*, sooo… Also, its syntax is pretty complex to be used anywhere an expression can be used. – deceze Aug 20 '23 at 22:29
  • @deceze `if-else` is also called _statement_ but then we can do `x = 1 if True else 2` – Abhijit Sarkar Aug 20 '23 at 22:30
  • 6
    That’s a completely separate operator, which is also greatly simplified to just two possible alternatives (i.e. no `elif`). – deceze Aug 20 '23 at 22:32
  • 2
    @AbhijitSarkar that is a *conditional expression* which is distinct from an if statement. – juanpa.arrivillaga Aug 20 '23 at 22:36
  • 2
    You can use the good ol' `{ 'John': 'Jane', 'David': 'Alice' }` instead. Of course, this relies on hashing and is not even remotely as good as what `match`/`case` does. – InSync Aug 20 '23 at 22:50
  • Another choice is to extract the `match`/`case` part to a dedicated function where `return` can be freely used without preventing later lines of being executed. – InSync Aug 20 '23 at 22:55
  • @InSync Yes, of course, but that seems forced to me. Anyway, I think I got the answer to my question, which is "it can't be done." – Abhijit Sarkar Aug 20 '23 at 22:57
  • Post that as an answer then. As far as I know it is correct. – InSync Aug 20 '23 at 22:58
  • It's worth noting that there's no fallthrough on your hypothetical example. Maybe that helps clarify why it's not possible. – wjandrea Aug 21 '23 at 00:40
  • 1
    Related: [Replacements for switch statement in Python?](/q/60208/4518341) – wjandrea Aug 21 '23 at 00:41

2 Answers2

5

No, the match statement cannot be used as an expresssion.

This is addressed in the Rejected Ideas section of PEP 622:

Make it an expression

In most other languages pattern matching is represented by an expression, not statement. But making it an expression would be inconsistent with other syntactic choices in Python. All decision making logic is expressed almost exclusively in statements, so we decided to not deviate from this.

Brian61354270
  • 8,690
  • 4
  • 21
  • 43
2

Not in Python.

In Rust and Haskell, matches are expressions composed of expressions:

let spouse = match name {
    // expr => expr,
    "John" => "Jane",

    // expr => {stmt; stmt; expr},
    "David" => {let s = "Alice"; println!("Matched David"); s},

    _ => panic!("Unknown name"),
};
do
  spouse <- case name of
    "John" -> return "Jane"
    "David" -> do
      let s = "Alice"
      putStrLn "Matched David"
      return s

...so it's not technically impossible that the Python match statement couldn't have been designed to work as an expression. Presumably, the reason it was avoided for Python are syntactical reasons:

  1. Python does not have syntax for expression statements (e.g. {stmt; stmt; expr}).

    spouse = match name:
        case "John":
            "Jane"
        case "David":  # stmt; stmt; expr
            s = "Alice"
            print("Matched David")
            s
    
  2. Indentation to indicate a block being treated as an expression may look unnatural to some people. (See also: match grammar.)

That said, it is possible your proposed syntax could be accepted in the future.

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135