Skip to content

Instantly share code, notes, and snippets.

@kschiess
Created August 17, 2011 13:51
Show Gist options
  • Save kschiess/1151562 to your computer and use it in GitHub Desktop.
Save kschiess/1151562 to your computer and use it in GitHub Desktop.
A matcher thingy.
class Matcher
def initialize(expr)
@expr = expr
end
def ===(value)
@bindings = {}
match(@expr, value, @bindings)
end
end
module ExpressionMatcher
class Wildcard
def matches?(value, bindings)
true
end
end
class Binding
def initialize(name)
@name = name
end
def matches?(value, bindings)
if old_value=bindings[@name]
return old_value == value
else
bindings[@name] = value
return true
end
end
end
def match(expr, value, bindings={})
case expr
when Array
expr.zip(value).all? { |expr_el, val_el|
# p [:ary_match, expr_el, val_el]
match_el(expr_el, val_el, bindings) }
else
match_el(expr, value, bindings)
end
end
def match_el(expr, value, bindings)
# p [:match_el, expr, value, bindings]
if expr.respond_to?(:matches?)
return expr.matches?(value, bindings)
end
expr == value
end
def any
Wildcard.new
end
def b(name)
Binding.new(name)
end
end
include ExpressionMatcher
# p match('a', 'a')
# p !match('a', 'b')
# p match(%w(a b), %w(a b))
# p !match(%w(a b), %w(a c))
# p match(any, 'a')
#
# b = {}
# p match(b(:x), 'a', b)
# p b
# p match([1,b(:x),any], [1,2,3])
# message = [:destroy, 1234]
# case message
# when m=m(:destroy, b(:obj))
# destroy(m.obj)
# end
def test(*value)
case value
when m=Matcher.new([1,2,3])
p [:zero, m]
when m=Matcher.new([3,b(:x), any])
p [:first, m]
when m=Matcher.new([2,b(:x), any])
p [:second, m]
end
end
test(1,2,3)
test(3,2,3)
test(2,3,4)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment