<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Michael Keene</title>
    <description>The latest articles on DEV Community by Michael Keene (@michaelkeene).</description>
    <link>https://dev.to/michaelkeene</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1792683%2F556c1962-5525-4be1-8d26-f4e445392cc0.png</url>
      <title>DEV Community: Michael Keene</title>
      <link>https://dev.to/michaelkeene</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/michaelkeene"/>
    <language>en</language>
    <item>
      <title>The Strangest Ruby Syntax: PatternMatching</title>
      <dc:creator>Michael Keene</dc:creator>
      <pubDate>Tue, 30 Jul 2024 12:31:46 +0000</pubDate>
      <link>https://dev.to/michaelkeene/the-strangest-ruby-syntax-patternmatching-30pk</link>
      <guid>https://dev.to/michaelkeene/the-strangest-ruby-syntax-patternmatching-30pk</guid>
      <description>&lt;p&gt;Ruby has supported pattern matching objects since version 2.7, and with it introduced some of the strangest Ruby syntax.&lt;/p&gt;

&lt;p&gt;Through this article I aim to start small and build to explain how&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;year: &lt;/span&gt;&lt;span class="no"&gt;Integer&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;year_of_birth&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is valid Ruby (in pattern matching).&lt;/p&gt;

&lt;p&gt;This article, with some bonus content, and all the code examples are available in a &lt;a href="https://gist.github.com/Michaelkeene/76bc9dc86ec950d5d355c261817b533e" rel="noopener noreferrer"&gt;runnable gist&lt;/a&gt;, feel free to play with them after reading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro to pattern matching
&lt;/h2&gt;

&lt;p&gt;pattern matching allows us to compare classes of objects&lt;/p&gt;

&lt;p&gt;using &lt;code&gt;case object; when Condition&lt;/code&gt; uses a simple === this ends up the same as &lt;code&gt;.call&lt;/code&gt; so we can pass lambdas or symbols converted to procs, which helps switch on more complex logic.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;case object; in Pattern&lt;/code&gt; is very different.&lt;br&gt;
To look at how the pattern definitions have changed case statements I'll take you on the same journey I went on, and in the process, explain that strange syntax from the first paragraph.&lt;/p&gt;

&lt;p&gt;Thinking of Patterns as some different object to normal ruby code&lt;br&gt;
helps us to reason about them correctly.&lt;/p&gt;

&lt;p&gt;After the &lt;code&gt;in&lt;/code&gt; keyword the ruby parser acts differently and we should think about it differently. My mental model is that it creates some sort of object, lets make up a PatternMatching::Pattern instance, and then it checks &lt;code&gt;pattern_matching_pattern.match?(object_at_start_of_case_statement)&lt;/code&gt;.&lt;br&gt;
I have a picture of how this (fictional) &lt;code&gt;.match?&lt;/code&gt; method works, which so far seems to match reality.&lt;/p&gt;
&lt;h3&gt;
  
  
  A familiar pattern
&lt;/h3&gt;

&lt;p&gt;using &lt;code&gt;in&lt;/code&gt; we can do essentially identical comparisons of class&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="no"&gt;Integer&lt;/span&gt; &lt;span class="c1"&gt;# comprable to value.is_a?(Integer)&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"value is an integer"&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"failed to check class properly?!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# in this case `in` is very similar to `when`&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
&lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="no"&gt;Integer&lt;/span&gt; &lt;span class="c1"&gt;# ===(value)&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"value is _still_ an integer"&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"failed to check class properly?!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but we can also match on the structure of an object and it's constituent parts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;
&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"there are three integers in the array"&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"what the heck is in there?!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# we can even *collect some of the contents in the same way as method *args and **kwargs.&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;
&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"the array starts with an Integer"&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"the rest of the array is &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"what the heck is in there?!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the first variable assignment done &lt;em&gt;by&lt;/em&gt; the pattern, this in itself feels quite powerful. This variable assignment is also the first part of the puzzle for our strange syntax in the opening paragraph.&lt;/p&gt;

&lt;h3&gt;
  
  
  Going deeper
&lt;/h3&gt;

&lt;p&gt;there are 2 methods that help with pattern matching on the internal state of objects&lt;/p&gt;

&lt;p&gt;deconstruct and deconstruct_keys&lt;br&gt;
along with 2 ways of declaring a patten of an object&lt;/p&gt;

&lt;p&gt;you can use an array pattern or a hash pattern&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Thing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:thing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Data already have the methods we need defined&lt;/span&gt;

&lt;span class="n"&gt;my_thing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Thing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;my_thing&lt;/span&gt;
&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="no"&gt;Thing&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"my_thing is a Thing instance"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;here the pattern is just the class &lt;code&gt;Thing&lt;/code&gt; matching the pattern here is the same as above and it will just check that my_thing is an instance of Thing&lt;br&gt;
something like:&lt;br&gt;
return false unless my_thing.is_a? Thing&lt;br&gt;
true&lt;/p&gt;

&lt;p&gt;now for some fun&lt;/p&gt;
&lt;h4&gt;
  
  
  Deconstruct
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;my_thing&lt;/span&gt;
&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="no"&gt;Thing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"my_thing holds an integer"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;to build this pattern it will work from the outside in&lt;br&gt;
reccursively checking that the class of the object is correct,&lt;br&gt;
then checking that the object.deconstruct matches the internal pattern&lt;/p&gt;

&lt;p&gt;To aid in the mental model I want to define a fictional class &lt;code&gt;PatternMatching::Pattern&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;N.B. I'm unaware of the &lt;em&gt;actual&lt;/em&gt; details of the pattern matching internals,&lt;br&gt;
This is a fictional class I use as a mental model, a product of my own tinkering, failures and successes.&lt;/p&gt;

&lt;p&gt;I picture the process like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;PatternMatching&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Pattern&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="ss"&gt;klass: &lt;/span&gt;&lt;span class="no"&gt;Thing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;internal_pattern: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;PatternMatching&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Pattern&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;klass: &lt;/span&gt;&lt;span class="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;internal_pattern: &lt;/span&gt;&lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then each PatternMatching::Pattern checks if the objects, class matches the klass, then defers to the &lt;code&gt;internal_pattern.match?(object.deconstruct)&lt;/code&gt; till we reach the end of the tree&lt;/p&gt;

&lt;p&gt;we could also see this as nested checks &amp;amp;&amp;amp; case statements.&lt;br&gt;
e.g This is equivalent to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;my_thing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_a?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Thing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;my_thing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deconstruct&lt;/span&gt;
                         &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                           &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"my_thing holds an integer"&lt;/span&gt;
                         &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have discovered no limit to the nesting&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;OtherThing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Struct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;other_thing_1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;OtherThing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;other_thing_2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;OtherThing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;other_thing_1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;other_thing_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;other_thing_2&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;other_thing_1&lt;/span&gt;
&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="no"&gt;OtherThing&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;OtherThing&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;OtherThing&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;OtherThing&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;OtherThing&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;OtherThing&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;OtherThing&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;OtherThing&lt;/span&gt;&lt;span class="p"&gt;]]]]]]]&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"at each stage it compares the internal pattern to `object.deconstruct`"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I feel like I can hear your next thoughts, something along the lines of:&lt;br&gt;
but that has all the disadvantages of positional args, with complex state this will be a pain to manage,&lt;br&gt;
there must be a better way!&lt;br&gt;
deconstruct_keys to the rescue&lt;/p&gt;
&lt;h4&gt;
  
  
  Deconstruct keys
&lt;/h4&gt;

&lt;p&gt;deconstruct_keys can be defined on any object and as with deconstruct, it is already defined on Struct and Data.&lt;br&gt;
This method recieves an array of keys and then responds with a hash, matching those keys to values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;my_thing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deconstruct_keys&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="ss"&gt;:thing&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;thing: &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"we can specify the kwargs we care about and discard the rest"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the second part of our puzzling syntax, we are able to specify the class of the value for each key! Strategy patterns on complex objects, validation of user input, to flex on people holding onto ruby &amp;lt; 2.7, this is the next game changing powerup that pattern matching affords us.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;my_thing&lt;/span&gt;
&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="no"&gt;Thing&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;thing: &lt;/span&gt;&lt;span class="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"this will check the class of my_thing matches Thing"&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"and my_thing.deconstruct_keys(:thing)[:thing] matches Integer"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to this end, in a similar vein to deconstruct, we can compare deeply nested structures&lt;/p&gt;

&lt;p&gt;N.B. not an actual suggested way to represent data, just a toy example.&lt;br&gt;
Also not that deep.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;json_stuff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="ss"&gt;person: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s2"&gt;"Michael Keene"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;birthday: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="ss"&gt;year: &lt;/span&gt;&lt;span class="mi"&gt;1992&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;month: &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;day: &lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;json_stuff&lt;/span&gt;
&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;person: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;birthday: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;year: &lt;/span&gt;&lt;span class="n"&gt;year_of_birth&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;
  &lt;span class="c1"&gt;# we apparently only care about this guys birthday&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"this person was born in &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;year_of_birth&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="c1"&gt;# this assignment by the pattern is cool&lt;/span&gt;
  &lt;span class="c1"&gt;# but how do we compare to an existing and defined value?&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Comparing to specific values - Carat pins
&lt;/h3&gt;

&lt;p&gt;Comparing the structure of classes and the keys of deconstruct keys are fine and dandy, along with the ability to assign some of the constituent parts to variable names (assuming a match)&lt;br&gt;
is already affording us some strong posibilities. However an obvious question soon bubbles up, can I compare to existing variables? These variables could be from an external yml configuration or something only set during runtime, there would be no other way to hard code them, are we doomed to compare these things with only &amp;lt; 2.7 syntax?&lt;br&gt;
Thankfully that is not the case :)&lt;/p&gt;

&lt;p&gt;N.B. This doesn't connect much to the initial strange syntax, other than it is a natural extension of what we have learned so far.&lt;/p&gt;

&lt;p&gt;a naive attempt would just to be using the same variable in the same place&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;nonesense&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ASdansdflnlnn"&lt;/span&gt;
&lt;span class="n"&gt;cool_guy_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Michael Keene"&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;json_stuff&lt;/span&gt;
&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;person: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="n"&gt;nonesense&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"The persons name has now been assigned to the variable `nonesense`"&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"this is because we need to pin the value with a carat ^"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but much like regular reassignment&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"foo"&lt;/span&gt;
&lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"bar"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the pattern will assign the value for the key to the variable name, regardless of what it was.&lt;/p&gt;

&lt;p&gt;So let see the difference if we try once more but with a carat&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;nonesense&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ASdansdflnlnn"&lt;/span&gt; &lt;span class="c1"&gt;# reset value of nonesense&lt;/span&gt;

&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;json_stuff&lt;/span&gt;
&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;person: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;nonesense&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="s2"&gt;"that name is too stupid"&lt;/span&gt;
&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;person: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;cool_guy_name&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"what a cool guy: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;cool_guy_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This correctly identifies me as a cool guy, as the carat before the symbol indicates that the pattern should compare to the actual already defined variable. Very nice stuff indeed.&lt;/p&gt;

&lt;p&gt;so now we see that the mental model we have PatternMatching::Pattern has a series of different checks it can do, as well as variable assignment. Checking the docs for accepted patterns we see the list includes:&lt;/p&gt;

&lt;p&gt;is the klass the object.class ?&lt;br&gt;
does the object.deconstruct match the position internal pattern ?&lt;br&gt;
does the object.deconstruct_keys match the kwarg internal pattern ?&lt;br&gt;
is the object.eql? to this pinned value ?&lt;br&gt;
we can also use | to split up different patterns for the same case branch&lt;/p&gt;

&lt;p&gt;there are some extraneous things with ranges that I won't cover in detail, but basically they have to be bracketed and pinned to be understood by the PatternMatching::Pattern builder&lt;/p&gt;

&lt;p&gt;There is now a hole in the checks we can do&lt;br&gt;
going back up to this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;json_stuff&lt;/span&gt;
&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;person: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;birthday: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;year: &lt;/span&gt;&lt;span class="n"&gt;year_of_birth&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;
  &lt;span class="c1"&gt;# we apparently only care about this guys birthday&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"this person was born in &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;year_of_birth&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="c1"&gt;# this assignment by the pattern is cool&lt;/span&gt;
  &lt;span class="c1"&gt;# but how do we compare to an existing and defined value?&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We know we can assign values to variables, and we know we can check the class of a value, but how do we both assign to a variable (in this case year_of_birth) and check it's class? we could use something like &lt;br&gt;
&lt;code&gt;in {person: {birthday: {year: Integer}}}&lt;/code&gt;&lt;br&gt;
and then dig(:person, :birthday, :year) but that feels inefficient, and in the clean clear world of pattern matching that just won't do.&lt;/p&gt;

&lt;p&gt;No! There must be a better way. If you look back to the article intro, there is.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;json_stuff&lt;/span&gt;
&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;person: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;birthday: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;year: &lt;/span&gt;&lt;span class="no"&gt;Integer&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;year_of_birth&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt; &lt;span class="c1"&gt;# this is valid Ruby!&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"this person was born in &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;year_of_birth&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; and it's an Integer!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well gang, we got there! To me this looks strange as hash rockets typically go &lt;code&gt;{key =&amp;gt; value}&lt;/code&gt; and are no longer required with symbol keys &lt;code&gt;{key: value}&lt;/code&gt;. Having &lt;em&gt;both&lt;/em&gt; feels peculiar &lt;code&gt;{key: Value =&amp;gt; other_value}&lt;/code&gt;, like a three layered fraction, it doesn't yet sit right with me but I'm sure that will ease with time.&lt;br&gt;
To me this really solidifies the fact that the Ruby parser&lt;br&gt;
does something &lt;em&gt;very&lt;/em&gt; different after the &lt;code&gt;in&lt;/code&gt; keyword.&lt;/p&gt;

&lt;p&gt;In our new shining world of pattern matching and hash value ommission I almost forgot to consider the other place&lt;br&gt;
where values are assigned to variables based on the key that they have, method definitions!&lt;br&gt;
Yes friends I can see a world where one day this syntax could be used in a similar fashion with method args and kwargs,&lt;br&gt;
to offer clear explicit type requirements in method definitions for method arguments.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
