Pattern Match Fall-through with ignored variable fails to compile

Minimal example:

type foo =
| Bar(int)
| Baz((string, int))

let aFoo = Bar(2)

let qux = switch aFoo {
        | Bar(y)
        | Baz((_x, y)) => y
}

This results in an error I don’t understand:
Variable _x must occur on both sides of this | pattern
Removing the fall-through fixes the error. Example:

type foo =
| Bar(int)
| Baz((string, int))

let aFoo = Bar(2)

let qux = switch aFoo {
        | Bar(y) => y
        | Baz((_x, y)) => y
}

I didn’t expect that to work. I couldn’t find anything about it in the docs either: Pattern Matching / Destructuring | ReScript Language Manual

playground link:
https://rescript-lang.org/try?code=C4TwDgpgBAZg9nKBeAUAHygIQIYCcAUAlgHbACU6W2AXvvgM7C4kDmANFCeRSgDYTAo2AGIJkVAgCYe-QQEcArgA9x9AO6FgAYwAWQ0YgDeKKKbOmMOAiDLIAfFBAnzZyzToB9JRxu2kDpwBfIA

Prefixing a value with _ doesn’t actually ignore it in the sense that the value is explicitly discarded. It only suppresses “unused variable” warnings. When you bind it to _x, it’s still possible for you to reference the binding _x later if you wanted to.

To completely ignore the value, i.e. make it impossible to reference later, you need to bind it to _ exactly (not just prefix it). This should compile as you expect:

type foo = Bar(int) | Baz((string, int))

let aFoo = Bar(2)

let qux = switch aFoo {
| Bar(y) | Baz((_, y)) => y
}
2 Likes

Oh, that’s good to know. I think having a way to label ignored variables can make some code clearer, but I guess I’ll just use the underscore in this case.
Thanks for the answer.

One option is to use “inline records,” records defined inside variants. That way you can reference their arguments by label rather than by position:

type foo = Bar(int) | Baz({x: string, y: int})

let aFoo = Bar(2)

let qux = switch aFoo {
| Bar(y) | Baz({x: _, y}) => y
}
1 Like

The trick to remember here is that you’re not ignoring a variable, you’re ignoring a pattern. Nothing about the code specifies the first value in the tuple is x and the second is y. You’ve simply named the second value y in your pattern match.

If you need to name them explicitly, the record-based approach @johnj recommended is ideal.

1 Like