# Match

`match` chooses between the cases of a value. It must cover every case,
and it works as a statement or as a value. Its arms use `->`, the same
arrow as result types.

```jadpo
function receipt(outcome: PaymentOutcome) -> ReceiptId? {
    return match outcome {
        PaymentOutcome.pending -> none
        PaymentOutcome.paid(paid) -> paid.receipt_id
        PaymentOutcome.declined -> none
    }
}

function headline(listing: Listing) -> ProductName {
    return match listing.subtitle {
        some(subtitle) -> subtitle
        none -> listing.name
    }
}

action follow_up(todo: Todo) -> Unit {
    match todo.status {
        TodoStatus.open -> {
            notify_owner(todo.id)
        }
        TodoStatus.done -> {}
    }
}
```

A `match` on a call that can fail names its success value and each
failure ([Handling a failure in `match`](handling-a-failure-in-match.md)):

```jadpo
function lookup_or_default(key: LookupCode) fails LookupRejected -> LookupResult {
    return match lookup(key) {
        success(value) -> value
        LookupMissing -> "not found"
        LookupRefused -> reject LookupRejected
    }
}
```

| Pattern | Matches |
|---|---|
| `Enum.variant` | a plain variant, or a variant whose fields this arm doesn't read |
| `Enum.variant(name)` | a variant with fields, naming them `name`; `name.field` has the field's type, `Enum.variant.field` |
| `some(name)`, `none` | a nullable value |
| `true`, `false`, `"text"`, `42` | a literal |
| `_` | anything else; only where the cases can't be listed, such as text and numbers |
| `success(name)`, `FailureName` | the result of a call that can fail: its value, or one of its failures |

There is no `_` on an enum, a `Bool` or a nullable value: every case is
listed. So adding a variant to an enum makes every `match` that must
handle it fail to compile until it does.

An arm is one of:

- `pattern -> expression`;
- `pattern -> reject F`, which maps the failure to another;
- `pattern -> propagate`, which passes the failure on;
- `pattern -> { statements }`.

A failure arm can recover with a value, map to another failure with
`reject`, or pass the failure on with `propagate`. Every failure the call
can produce needs an arm ([Failures](failures.md)).
