Pattern: Erlang-style pattern matching in Ruby
Mostly for grins, I decided to implement Erlang-style pattern matching in Ruby on Sunday afternoon.
p.match(/lmao/) {:butts }
p.match(/lol/) {:buttes }
p.match(wc) {"atomics" }
p[888]
# => "atomics"
p["a butt lmao"]
# => :butts
p["lolqdb"]
# => :buttes
Fork/clone Pattern on Github, and read on for commentary.
How it works
In the example above, p is a Pattern::Matcher object, that wraps arguments and blocks from the #match
method into a Pattern::Entry object, and stores those objects in an array in order of definition. When
called with the #[] method, it goes through that array and calls the stored block from the first entry that
answers positively to Pattern::Entry#match?.
A Pattern::Entry is basically a tuple of an argument list and a proc to execute on match. The only real
cleverness is checking for a Pattern::Wildcard object, and checking with #===, which picks an appropriate
comparison for the objects involved (uses Regexp#=~ if the left value is a Regexp and right is a String,
for example.)
What could be done
Things I've got ideas for but haven't done yet include extending the Wildcard object to allow for Array#first
and Object#class (or Class#ancestors) checks, since those don't work with #===.