Ruby 2.7 introduced pattern matching as an experimental feature. As of Ruby 3.0, only small parts of pattern matching are still experimental, which means we can learn about the stable parts. Variable pinning is a new feature with pattern matching which we'll discuss in two consecutive tips. It's first necessary for us to understand the goals of pattern matching. From the docs, "Pattern matching is a feature allowing deep matching of structured values: checking the structure and binding the matched parts to local variables." Pattern matching uses the case/in/else expression, similar to the case/when/else expression. It allows us to match patterns, not just exact values: case [1,2]
in [1,a]
"pattern match: a: #{a}"
in [1,2]
"second case"
end
=> "pattern match: a: 2"
Woah! We can see that it matched the [1,a] case before the [1,2] case because our array matched the pattern [1,a] . And what's more: the value of a was then set to 2 , the second element of our array in the case statement. You may be wondering what would happen if we wanted to try pattern match against an existing local variable. Say we had already defined a before the case statement: a = 3
case [1,2]
in [1,a]
"pattern match: a: #{a}"
in [1,2]
"second case"
end
=> "pattern match: a: 2"
Uh-oh. What's going on? It's telling us a is 2 and seems to be overriding our local variable a , which has a value of 3 . This is where pinning comes in! If we wanted to use the local variable a , we would use the pin operator, ^ to signify that we were referrring to our local variable: a = 3
case [1,2]
# We'll now use ^a
in [1,^a]
"pattern match: a: #{a}"
in [1,2]
"second case"
end
=> "second case"
And we can see that with the pin operator, we no longer match the first case, which would be [1,3] . Just to confirm we could match the first case if the second element in our array was 3 , let's change our array to be [1,3] : a = 3
case [1,3]
in [1,^a]
"pattern match: a: #{a}"
in [1,2]
"second case"
end
=> "pattern match: a: 3"
Check back in next week for another use case of variable pinning! |