If you've ever done any assembly programming or worked with other old or low level languages, you may have encountered an environment where you can write simple operator expressions, but you can't compose them. So this is OK:
a = b + c
d = e - f
g = a * d
But the compiler doesn't allow:
g = (b + c) * (e - f)
You have expressions that produce, but they don't compose. You can't produce a value from a more complex, nested expression. We, rightly, no longer use languages like that.
Pattern matching parallels that, except for assignment and decomposing values. Many languages today let you write:
topLeft = rect.topLeft.x;
left = topLeft.x;
top = topLeft.y;
bottomRight = rect.bottomRight;
right = bottomRight.x;
bottom = bottomRight.y;
Or even:
left = rect.topLeft.x;
top = rect.topLeft.y;
right = rect.bottomRight.x;
bottom = rect.bottomRight.y;
(Because at least you can compose expressions on the RHS.) But they don't let you write:
(topLeft, bottomRight) = rect;
(left, top) = topLeft;
(right, bottom) = bottomRight;
Or even:
((left, top), (right, bottom)) = rect;
Pattern matching gives you that. It is freely composable destructuring.
Also, the "matching" part means that in many languages you can also ask questions about values as you destructure them, which enables a particularly nice style of programming.