Empower Pattern Matching in Ruby


RubyFunctional Programming

Ruby2.7 provides Pattern Matching feature as an experimental one.

I used to do pattern matching in Scala, so I’m excited to be able to use it in Ruby!


Rstructural Gem what I’ve been developing lets us coding more efficiently with pattern matching in Ruby.

What is Pattern Match?

This deck desribes it precisely.

It’s enough to know what is pattern match in Ruby, however, let me give some examples as followings,

case [1, 2, [3, [4, 5]]]
in [a, b, [*c]]
    puts "a+b: #{a+b}, rest:#{c}"
# => a+b: 3, rest:[3, [4, 5]]
case {a: 1, b: 2, c: {d: 3, e: [4, 5]}}
  in {a:, c: {d:, e: [4, x]}}
    puts "a: #{a}, c: #{c}, d: #{d}, x: #{x}"
# => a: 1, c: [3, [4, 5]], d: 3, x: 5
module HttpStatus
  OK = 200
  NotFound = 404
  InternalServerError = 500

case 500
in HttpStatus::OK
  puts "OK!"
in HttpStatus::NotFound | HttpStatus::InternalServerError
  puts "NG!"
in unknown
  puts "Unknown: #{unknown}"
# => NG!

Pattern Match brings a capability of intuitive expression to represent what code does.

Empower Pattern Matching

As you know, pattern matching is excellent. However, I’m eager to write Ruby codes more functional way as I do with Scala. Case class in Scala is to represent algebraic data types, and absolutely useful to write intuitive and expressive codes, especially when combining with pattern matching.

Thus, I import a kind of algebraic data type into the Ruby world. It is Rstructural gem.

Rstructural provides Enum and Algebraic Data Type(ADT), and also applied types(Option, Either).


The simplest ADT is Enum, I think. Unfortunately, Ruby does not have enum as default. On the other hand, Rails has ActiveRecord::Enum, but it’s for ActiveRecord as its name says so that the Enum is not for define data structure in pure Ruby world.

Rstructural provides Enum to define enumerated values.
It looks like:

require 'rstructural'

module HttpStatus
  extend Enum
  OK = enum 200
  NotFound = enum 404
  InternalServerError = enum 500

case HttpStatus.of(500) # factory
in HttpStatus::OK
  puts "OK!" # => OK!
in HttpStatus::NotFound | HttpStatus::InternalServerError
  puts "NG!"
in unknown
  puts "Unknown: #{unknown}"

# => true

Each enum value has a constant, and we can use them as a set of constants, HttpStatus in this example. Also, extending Enum injects a factory method of into the module. It brings us a sort of type-sensitive programming style. Another merit of using Enum is eliminating duplicated values, as:

module Status 
  extend Enum
  OK = enum 1
  NG = enum 2
  Unknown = enum 2
# => ArgumentError (Enum '2' already defined in Struct)

This feature protects us from defining wrong constants.


Rstructural::ADT brings characteristics of algebraic data type into Ruby module. An example to define ADTs:

module Shape
  extend ADT
  Point = const
  Circle = data :radius
  Rectangle = data :width, :height do
    def square?
      width == height
  interface do 
    def area
      case self
      in Point
      in Circle[radius]
        3.14 * radius * radius
      in Rectangle[w, h]
        w * h

rectangle =, 4)
# => 12
# => false
# => true

An ADT injected module has const and data to define data types.

  • const is to define a constant and look like a singleton object.

    • is similar to object in Scala
  • data :field_a, :field_b, ... is to define a type that holds given fields

    • is similar to case class in Scala

A combination of const and data in ADT module is similar to the one of object, case class, and sealed trait in Scala. As the example shows, it allows to define instance methods at the declaration of types and also give a block to interface.

Using ADT brings capabilities to manage a set of data types intuitively and type sensitive way as well as Enum.

Additionally, Rstructural gem provides Option and Either based on ADT. Please have a look if you are interested in.

Wrapping Up

I believe this kind of type abstraction would help you if you are familiar with functional programming way whether or not programming language provides static analysis.