I've been writing about
recursive structures and how to check
whether two objects are similar
for a while and I finally got to the code I wanted: recursion-safe "pattern
matching" over Ruby objects. This begins to feel more useful, and if
anything, it looks better.
Examples
We need a small class to show how this sort of pattern matching works,
something as simple as this will do:
class Nodeattr_accessor:a,:battr_reader:valuedef initialize(value,a,b)@a,@b=a,b@value=valueendend
Let's proceed to the first pattern: we will match any Node object and capture
its instance variables (@value, @a and @b):
matches all arrays such that the first element is the same as the last.
So let's do it:
pattern=Pattern.newdo|p|Node.new(p.capture(:value){""},nil,Node.new(p.capture(:value),nil,nil))end# matches a Node with a String value and whose 'right-child' is a node with the# very same value and no childrenmd=pattern.matchNode.new("some value",nil,Node.new("some value",nil,nil))# different values (in the object_id sense), no matchmd# => nils="whatever"md=pattern.matchNode.new(s,nil,Node.new(s,nil,nil))md[:value]# => "whatever"
Recursive captures
No way I could forget recursive stuff, right?
Here's another pattern, matching a node whose value is an array with three elements
of classes String, Fixnum and String (or derived, as usual), and referring to itself: