Pattern matching in Ruby

Paweł Świątkowski

@katafrakt_pl

Elixir, right?

case File.read(file) do
  {:ok, body}      -> # do something with the `body`
  {:error, reason} -> # handle the error caused by `reason`
end
defmodule Fib do 
  def fib(0) do 0 end
  def fib(1) do 1 end
  def fib(n) do fib(n-1) + fib(n-2) end
end

Fib.fib(10)
defmodule PhoenixGuardian.AuthController do
  use PhoenixGuardian.Web, :controller

  def callback(%{assigns: %{ueberauth_failure: fails}} = conn) do
    ...

  def callback(%{assigns: %{ueberauth_auth: auth}} = conn) do
    ...
end
  • Erlang
  • Elixir
  • Haskell
  • Scala
  • Rust
  • Swift
  • ...

Can we have it in Ruby?

Noaidi.match open_file(path) do |m|
  m.(:ok, File)         {|file| process_file(file) },
  m.(:error, Exception) {|ex| handle_file_opening_exception(path, ex) }
end
naive = Noaidi.module do
  fun :fib, [0] { 0 }
  fun :fib, [1] { 1 }
  fun :fib, [Integer] do |n|
    fib(n - 1) + fib(n - 2)
  end
end

puts naive.fib(5)
fizz = Noaidi.module do
  fun :buzz, [->(i) { i % 5 == 0 && i % 3 == 0}] do
    'FizzBuzz'
  end
  fun :buzz, [->(i) { i % 3 == 0}] do
    'Fizz'
  end
  fun :buzz, [->(i) { i % 5 == 0 }] do
    'Buzz'
  end
  fun :buzz, [Fixnum] do |n|
    n
  end
end

1.upto(100).each do |i|
  puts fizz.buzz(i)
end
class Adder < Concurrent::Actor::RestartingContext
  def initialize(init)
    @count = init
  end

  def on_message(message)
    Noaidi.match(message) do |m|
      m.(:add) { @count += 1 }
      m.(BasicObject) { pass }
    end
  end
end 

deck

By katafrakt

deck

  • 920