Ruby Features

Pattern Matching - New feature in Ruby 2.7

Pattern Matching - New feature in Ruby 2.7

by Kazuki Tsujimoto

In this talk presented by Kazuki Tsujimoto at RubyConf 2019, the focus is on the introduction of pattern matching as an experimental feature in Ruby 2.7. Tsujimoto, a member of the Ruby core team and the proposer of this feature, discusses the proposed syntax and design philosophy guiding its implementation.

Key points covered during the presentation include:

  • Definition and Functionality: Pattern matching is described as an advanced combination of case statements and multiple assignments, enabling developers to check object structures with patterns.
  • Implementation Use Cases: Practical examples illustrate how pattern matching can be applied to real JSON data, simplifying the syntax for complex condition checks.
  • Specifications: The syntax is aligned with existing Ruby case statements and allows for both sequential pattern evaluations and complexity through additional conditions.
  • Types of Patterns: Tsujimoto elaborates on six distinct patterns within Ruby's pattern matching:
    • Equality Compare: Uses the ‘===’ method for simple comparisons.
    • Variable Patterns: Binds values from patterns for reference.
    • Caution on Shadowing: Discusses how to avoid variable name conflicts using the caret (^) symbol.
    • Alternative Patterns: Matches any of the given patterns.
    • Destructuring Patterns: Extracts values from data structures, enhancing usability.
    • Hash Key Patterns: Retrieves values based on specified keys in hashes.
  • Design Philosophy: The Ruby team emphasizes compatibility with existing code, user-friendly interface, and operational performance as core guiding principles for the development of pattern matching. They aim to minimize disruption to current Ruby practices while providing a powerful new feature.

The talk concludes with a call for community feedback, encouraging Ruby developers to experiment with pattern matching and help shape its future. Tsujimoto expresses excitement for the potential impact of this feature on Ruby programming.

This session not only introduces a significant enhancement to Ruby but also highlights the collaborative and iterative nature of software development within the Ruby community.

00:00:13.700 My name is Kazuki Tsujimoto, and today I would like to talk about pattern matching. First, let me introduce myself. I am a member of the Ruby core team and also the proposer of pattern matching.
00:00:26.279 I'm also working on the RubyGems organization, which includes the Bundler gem. First, I would like to begin by providing an overview of what I want to communicate in this session.
00:00:39.270 Pattern matching has already been released in a preview version of Ruby 2.7, but it is still an experimental feature, and the specifications are still under discussion.
00:00:55.260 We are trying to identify real-world use cases that we can implement, and we hope to provide a convenient syntax. I would greatly appreciate it if you could try it out and give us feedback.
00:01:13.020 So this is the agenda for today: First, I'd like to define what pattern matching is and its functionality. Next, I will talk about the education supporting it, and finally, I will discuss the thought process behind the design.
00:01:34.590 So, what is pattern matching? Although it is difficult to define pattern matching in just a few words, a good summary can be found in a sentence taken from the Haskell tutorial: it is a combination of case statements and multiple assignments.
00:02:04.229 We extend case expressions for pattern matching in the current specification. We utilize case expressions, as they allow us to check object structures with patterns. In this case, if the variable's value is not as expected, the pattern match fails, and it moves on to the next pattern. If successful, this pattern requires the object to have the same structure.
00:02:46.290 What you need to pay attention to here is that there are not only variables but also values involved, allowing checkups on the object structure and assignments to variables simultaneously. This is a significant feature of pattern matching.
00:03:01.720 Pattern matching also supports hashes. For instance, if a pattern requires certain keys to have specific values and an object does not contain those keys or has unexpected values, like in the case of a key 'x' not being present, the pattern will not match.
00:03:44.390 This is a brief summary of data matching. Next, I would like to demonstrate real use cases of pattern matching. Here is an example of a session that allows you to use JSON data—if you look at the upper right side, there is information about a person, and there’s also a code printing their age if certain conditions are met. For instance, if the person's name is 'Heidi' and she has a child named 'Bob', it will retrieve and print Bob's age. The syntax allows you to write these conditions easily and clearly, making it a very significant aspect of pattern matching.
00:04:49.850 Next, I’ll talk about the specifications. Pattern matching is defined using case syntax, and patterns are evaluated sequentially. If no pattern matches, the default case is executed.
00:05:06.230 Additionally, it is possible to specify if-else statements or other additional conditions. This allows for complexity in conditions. For instance, you can specify that two variables must be different, and that condition will be taken into account during evaluation.
00:05:34.640 With the introduction of Ruby 2.7, pattern matching, which is a convenient syntactic sugar for different conditions, has been introduced.
00:06:01.900 Let me explain the different patterns within Ruby's pattern matching. There are six distinct patterns I will explain one by one. The first pattern is very straightforward—it compares an object using the ‘===’ method—this is very similar to case statements.
00:06:43.530 Next, we have variable patterns, where a variable can be used to bind a value from a pattern. This is particularly useful when pattern matching against more complex structures.
00:07:26.520 Moreover, if we are comparing objects, we need to be cautious about variable shadowing. If a variable in the outer scope has the same name as a variable in the pattern, it will be shadowed. To handle this, we can use the caret (^) symbol to indicate that we want to bind a new variable and not shadow the existing one.
00:08:13.990 The alternative pattern matches against any one of the given patterns. It's a straightforward concept, while the destructuring patterns extract values from data structures, binding them to variables as usual.
00:09:00.310 Next, we have the pattern that deals with nested structures, allowing binding within complex objects, which makes it easier to refer back to values as needed.
00:09:45.990 The last pattern is based on constant matching which, rather than pattern matching, allows comparisons that involve a specific class type. This means that we can check if an object is an instance of a certain class and then operate accordingly.
00:10:40.610 In a similar fashion, the structure matching provides a means of destructuring into variables while matching against a structure.
00:11:19.920 Continuing on, the next type of pattern matching consists of using the keys from hash structures. This allows obtaining values associated with keys from hashes. The constructor method operates similarly to destructuring while enabling extraction of values.
00:12:11.460 Next, we have the destructuring of nested structures where we can access nested patterns inside hashes and arrays.
00:12:52.080 I would now like to cover how the Ruby team has built the design philosophy behind these pattern matching features. The main guiding principles include compatibility, usability, and providing functionality that balances performance.
00:13:44.550 We are ensuring that existing Ruby code will not break when introducing these new features; thus, careful consideration has been given to existing syntax. We avoid reserving new keywords to ensure full compatibility. The design is aimed at fitting seamlessly with current conventions.
00:14:50.180 Furthermore, I believe we need to provide an easy-to-use interface allowing users to adopt pattern matching without confusion. Our focus is on enabling developers to leverage the power of pattern matching without sacrificing clarity or ease of use.
00:15:45.780 We will also work on documentation and examples to thoroughly explore pattern matching in practical use cases. Feedback from the community will greatly assist in this regard.
00:16:28.270 With that said, I’m looking forward to sharing this feature with the Ruby community and seeing how it evolves through your contributions.
00:16:57.030 Thank you for your attention.