00:00:00.120
Oh my gosh.
00:00:33.899
Foreign.
00:00:46.620
I hope you are ready for the last talk before our big break, where we will see each other in the hallway.
00:00:53.340
Our next talk is by Brandon Weaver.
00:01:02.070
Thank you.
00:01:15.320
Welcome, Brandon! Great to be here. The talk today is interesting for two reasons.
00:01:22.080
First, it’s about pattern matching, which is something relatively new in the Ruby world.
00:01:27.659
Second, it’s about poker. Brandon is a Ruby architect at Square.
00:01:34.500
He helps his company define standards for Ruby and is also an artist. I would love to hear more about lemurs and cartoons in programming afterwards.
00:01:42.240
Welcome, glad to be here. I guess I can leave the stage to you.
00:02:22.800
Hello, everyone! So glad you can make it.
00:02:27.900
Get comfy because we’re about to go on a wild ride through the depths of Ruby pattern matching.
00:02:35.099
This talk explores some novel usages and ideas regarding this exciting feature.
00:02:42.239
So who exactly am I? Simply put, my name is Brandon, I work for Square, and I enjoy doing fun things with Ruby.
00:02:49.319
You can find my Twitter in the bottom left of most slides, which will have resources related to the talk.
00:02:55.860
Shall we get started? Let’s begin with a short preview of pattern matching to see what it looks like.
00:03:07.860
The following code may have been common in older versions of Ruby, but with 2.7, we introduced a new syntax for pattern matching.
00:03:15.060
With this code, we compare values using triple equals.
00:03:20.640
We’ll primarily look at array-like matchers today.
00:03:27.959
This compares each element positionally; the first should be an integer, the second should be a two, and the third should just be there.
00:03:34.319
This also captures nil, but it does serve a useful purpose.
00:03:41.040
There’s also experimental one-liner syntax which I’ll be using heavily in this talk.
00:03:47.640
Based on its usefulness and documented use cases, I believe it will likely be included in future versions of Ruby.
00:03:54.720
I certainly hope so, because it’s all types of fun.
00:04:05.400
So, where were we? Ah, yes. I like lemurs, and lemurs like games.
00:04:12.659
They figured out how to play poker but are horrible at scoring the games, so they’ve asked us to help.
00:04:18.900
That brings us to the task of employing pattern matching.
00:04:24.720
To start, we'll need to set up some structure for our game, like a card or maybe a hand.
00:04:33.660
Let’s start with something simple, like creating a single card.
00:04:40.259
We can create a class to describe our card, starting with constants.
00:04:47.340
Constants will describe what our data is, how we validate it, and give us structure.
00:04:54.900
The suits will be S for Spades, H for Hearts, D for Diamonds, and C for Clubs.
00:05:00.300
Unicode symbols could be used, but using letters is quicker and easier.
00:05:06.660
Next, we need to consider ranks.
00:05:12.240
Ranks go from 2 up to Ace, and we typically use strings to avoid having to deal with numbers downstream.
00:05:18.360
We want numerical indices for each rank to reference their associated scores.
00:05:25.560
Now we have constants to describe the data of our class.
00:05:31.020
Next, we need to make a card, which is a combination of a suit like Spades and a rank like Ace.
00:05:36.660
Now let’s take a look at creating a hand, which is a collection of many cards.
00:05:43.620
To start, we want to define constants for our hand class.
00:05:49.560
The highest type of hand is a royal flush, and the lowest is a high card.
00:05:55.800
We’ll go into each one of these examples later in the talk.
00:06:01.860
After establishing those scores, we’ll create a list in reverse order to see that the royal flush has the highest score.
00:06:07.620
Now, let’s take a look at how hands are actually constructed.
00:06:13.740
A hand is a container for many cards, initialized with those cards.
00:06:19.740
You might notice one piece of code that is crucial for this layer – the sort method.
00:06:26.580
We want to have some methods to make it easier to create card hands and view their contents.
00:06:31.740
Let's consider viewing a card by implementing an array-bracket method.
00:06:38.640
This serves as an effective alias for the new method.
00:06:44.880
You might also notice a dot dot dot, which forwards all arguments.
00:06:50.160
Now, back to our card; we also want to have string and array representations.
00:06:56.250
Nothing too exciting here, just using one-liner methods for quick definitions.
00:07:02.040
We have a method called deconstruct, which is important for pattern matching.
00:07:09.060
This tells our class how to match against array-like patterns when asked.
00:07:15.840
Next, we’ll look at methods for creating and viewing our hands.
00:07:22.020
The hand class can define a similar method to from string to create it.
00:07:28.200
We want string and array representations along with pattern matching capabilities.
00:07:35.160
Now let’s get into actually creating a hand.
00:07:41.580
We can split the input string on either commas or spaces to allow multiple formats.
00:07:48.600
We can map these into cards using the underscore for numbered brands.
00:07:54.040
The sort method helps order our cards after mapping.
00:08:01.140
Now we should consider how to actually sort the cards.
00:08:07.440
We can start by defining card precedence to determine their rank.
00:08:13.740
We'll define the precedence for each card to score them against one another.
00:08:20.040
The interface for comparable enables us to use the rocket ship operator for comparisons.
00:08:29.100
This means we can sort them with ease.
00:08:36.540
Let’s consider comparing cards to see how this works.
00:08:42.840
If the left side is greater than zero, they are the same, and if negative, the right is greater.
00:08:50.040
As we sort the hand, we want to ensure the order is consistent for pattern matching.
00:08:57.560
This reduces potential match cases significantly.
00:09:05.160
With all this set up, we still need to focus on scoring.
00:09:12.180
Let’s explore some examples of scoring hands.
00:09:17.579
Our first hand is a royal flush, consisting of all cards of the same suit from ten to ace.
00:09:23.580
We’ll define methods on our hand to establish what constitutes a royal flush.
00:09:29.580
By matching our cards against a pattern, we can encapsulate this idea.
00:09:35.880
The pattern will start with a card with brackets.
00:09:42.300
This captures the suit and specifies the first rank must be ten.
00:09:48.600
We’ll ensure that all subsequent cards have the same suit.
00:09:55.920
Now, let’s test that out to see if it works.
00:10:01.019
This brings us to our next hand: a straight flush.
00:10:06.300
A straight flush requires all cards to be in order and of the same suit.
00:10:11.100
Unlike the royal flush, we need to define both conditions.
00:10:16.740
If both of these exist, our test returns true.
00:10:22.260
Next up is four of a kind. This means four cards of the same rank.
00:10:27.600
With four aces of different suits, we can check that our cards match this pattern.
00:10:33.300
As in previous cases, we’ll pin the rank to ensure the four cards are the same.
00:10:39.120
Now we’ll define a full house, which consists of three of one rank and two of another.
00:10:47.280
For this, we’ll match three aces and two kings.
00:10:54.480
We need to ensure we account for both rank configurations.
00:11:00.720
Next, we’ll establish a flush: all cards of the same suit.
00:11:05.520
We’ll match against all cards in the hand for the same suit.
00:11:12.300
After that, we can define a straight: all cards in order but any suit.
00:11:18.840
To implement this, we must define what the next card in the sequence is.
00:11:25.680
In the hand class, we'll check that ranks increase by one.
00:11:31.560
Though not an ideal solution, for now we must use string interpolation.
00:11:38.760
Back to our examples, a hand can be identified as a straight.
00:11:43.620
Next, we’ll look at three of a kind: three cards of the same rank.
00:11:50.280
Using the fine pattern method again, we’ll ensure we have those three cards.
00:11:57.060
Two pairs are next, which are two pairs of the same ranked card.
00:12:03.840
We’ll define a method to match against those pairs.
00:12:10.680
The issue is that we must ensure the pairs are distinct.
00:12:17.280
Finally, we have a single pair; this is like two pairs, but only one.
00:12:23.520
In testing, we’ll confirm our scoring implementation is effective.
00:12:29.880
With our foundation established, we can implement scoring for hands.
00:12:35.760
Using our scores, we can rank hands based on their types.
00:12:41.520
If nothing else matches, we can return the highest card.
00:12:48.300
Let’s run some examples to see if they all work.
00:12:54.060
Now we’ll check our constants.
00:13:01.080
If we run these tests, we will find that we can solve poker hands with pattern matching.
00:13:07.740
Pattern matching is an exciting feature with a multitude of possibilities.
00:13:14.400
I hope this talk inspires you to try a few of your own ideas.
00:13:23.220
Pattern matching has immense potential, especially when considering hash-like matching.
00:13:32.160
For those interested in more examples, you can follow my work on social media platforms.
00:13:44.940
I would like to thank everyone who contributed to the development of pattern matching.
00:13:54.540
It’s a community effort that continues to advance Ruby.
00:14:07.020
Thank you all for your time, and have a great day!
00:14:46.800
Welcome back! That was as great as I was expecting.
00:15:01.400
Thank you so much for your talk! It was an interesting deep dive into pattern matching and poker.
00:15:11.340
While we wait for questions, could you share where else you see pattern matching being utilized in the programming community?
00:15:21.660
Arrays tend to be the less powerful variant, which needs explanation.
00:15:33.080
What's fascinating is when you utilize hash-like matches, for example, matching HTTP responses.
00:15:43.080
With the expressive capabilities of pattern matching, you can perform complex queries on structured data.
00:15:53.040
This can be beneficial for processing JSON or CSV data easily.
00:16:00.540
In production, there could be numerous applications.
00:16:06.060
Historically, people shunned IF statements, but pattern matching provides clarity and enhances readability.
00:16:18.060
In Rails, we're exploring its use in models to facilitate data exploration.
00:16:28.620
It's especially useful during live coding or interacting with production data.
00:16:39.180
Pattern matching requires a deconstruct method to function effectively.
00:16:48.480
We’re advocating for support of this in various libraries and gems.
00:17:00.180
The community has yet to fully realize its potential but is making strides.
00:17:07.140
Thank you, let's keep exploring pattern matching together.