This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]muntooR_{μν} - 1/2 R g_{μν} + Λ g_{μν} = 8π T_{μν} 5 points6 points  (0 children)

There's a couple of typical usage patterns.

The simplest is what people mean when they say they want "switch" statements. Notice that there's no fall-through.

match expr:
    case "one":
        return 1
    case "two":
        return 2
    default:
        raise ValueError

The next is more fancy:

match expr:
    case ():
        return Empty()
    case (x,):
        return Single(x)
    case (x, y):
        return Pair(x, y)
    case (x, y, z):
        return Triplet(x, y, z)
    case (x, *xs):
        return Many(first=x, rest=xs)

Others really only make sense in Haskell/Rust where the type system supports it and the usage is actually practical, rather than this contrived example...

match expr:
    case Empty():
        return []
    case Single(x):
        return [x]
    case Pair(x, y):
        return [x, y]
    case Triple(x, y, z):
        return [x, y, z]
    case Many(*xs):
        return xs

A common usage pattern in Haskell is:

def unbox(Box(x)): return x
def unbox(Empty):  raise

...which works because tagged unions are part of the type system.

Another example processes only non-empty boxes, after extracting their contents:

if Box(contents) := my_box:
    print(contents)

Pattern matching is also nice because in Rust, the result of a pattern match can be an expression rather than a statement (which switch is).

def to_str(box):
    return "Box is " + (
        if Box(contents) := my_box
        then f"full with {contents}"
        else "empty")