Skip to content

Instantly share code, notes, and snippets.

@jodosha
Created September 29, 2021 07:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jodosha/5b1262dc7af1cade8fd1bf0e2ffd8d7b to your computer and use it in GitHub Desktop.
Save jodosha/5b1262dc7af1cade8fd1bf0e2ffd8d7b to your computer and use it in GitHub Desktop.
Give Ruby 3 an Elixir flavor: provide pattern matching for recursion
# frozen_string_literal: true
module PatternMatching
def self.extended(base)
base.class_eval do
@__pn_methods = {}
end
end
def __pn_methods
@__pn_methods
end
def deff(method_name, pattern, &blk)
__pn_methods[method_name] ||= {} # FIXME: make me thread-safe
__pn_methods[method_name][pattern] = blk
define_singleton_method(method_name) do |*args, **kwargs|
__pn_methods[method_name].each do |pn, b|
match = begin
pn.call(*args, **kwargs)
true
rescue NoMatchingPatternError
false
end
return b.call(*args, **kwargs) if match
end
raise NoMatchingPatternError
end
end
def pn(&blk)
blk
end
end
class Fib
extend PatternMatching
deff :call, (pn { |n| n => 0 }) do
0
end
deff :call, (pn { |n| n => 1 }) do
1
end
deff :call, (pn { |n| n => Integer }) do |n|
call(n - 1) + call(n - 2)
end
end
puts Fib.call(10)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment