Skip to content

Instantly share code, notes, and snippets.

@kddnewton
Created October 28, 2022 15:07
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save kddnewton/c4f7f1226e0831a025aa29def7d9a6d6 to your computer and use it in GitHub Desktop.
Pattern matching
# This module is a light implementation of pattern matching that allows us to
# match against hashes and arrays as we would with the new pattern matching
# syntax.
module Pattern
class ArrayPattern
attr_reader :values
def initialize(values)
@values = values
end
def ===(other)
deconstructed = other.deconstruct
values.each_with_index.all? do |value, index|
value === deconstructed[index]
end
end
end
class HashPattern
attr_reader :values
def initialize(values)
@values = values
end
def ===(other)
deconstructed = other.deconstruct_keys(values.keys)
values.all? do |key, value|
value == :any ? deconstructed.key?(key) : value === deconstructed[key]
end
end
end
def self.[](value)
case value
when Array
ArrayPattern.new(value.map { |child| self[child] })
when Hash
HashPattern.new(value.transform_values { |child| self[child] })
else
value
end
end
end
require "json"
source = '{ "a": 1, "b": [2, 3], "c": "Hello, world!" }'
case JSON.parse(source, symbolize_names: true)
when Pattern[a: 1] # <-- match against individual values
puts "Matched value!"
when Pattern[b: [2, 3]] # <-- match against lists of values
puts "Matched list!"
when Pattern[a: Integer] # <-- match against classes
puts "Matched class!"
when Pattern[c: /Hello/] # <-- match against regular expressions
puts "Matched regular expression!"
when Pattern[a: :any] # <-- match against any value
puts "Matched wildcard!"
else
puts "No match!"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment