Skip to content

Instantly share code, notes, and snippets.

@rklemme
Created June 21, 2009 11:40
Show Gist options
  • Save rklemme/133488 to your computer and use it in GitHub Desktop.
Save rklemme/133488 to your computer and use it in GitHub Desktop.
Alterntaive to visitor pattern
class Visitor
def traverse(enum)
enum.each do |node|
visit node
end
self
end
def visit(node)
node.class.ancestors.each do |cl|
m = get_method_name cl
return send(m, node) if respond_to? m
end
raise ArgumentError, "Do not know how to visit #{node.inspect}"
end
private
def get_method_name(cl)
"visit_#{cl.name.gsub(/::/, '_')}".freeze
end
end
class DumpVisitor < Visitor
def visit_Object(o)
p o
end
end
DumpVisitor.new.traverse %w{foo bar baz}
class OptimizedVisitor < Visitor
def initialize(*a,&b)
super
@cache = Hash.new do |h, cl|
f = cl.ancestors.each do |acl|
m = get_method_name acl
break(h[cl] = method(m)) if respond_to? m
end
raise ArgumentError, "Do not know how to visit #{cl.inspect}" unless Method === f
f
end
end
def visit(node)
@cache[node.class][node]
end
end
class DumpVisitor2 < OptimizedVisitor
def visit_Object(o)
p o
end
end
DumpVisitor2.new.traverse %w{foo bar baz}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment