Re:How Arel Converts Ruby Queries into SQL Statements
by vidarh on Tuesday June 30, 2015 @03:15PM
(#9807744)
Sort-of, kind-a. The visitor pattern is about providing a mechanism where you can encapsulate behaviour separate from the model. So it's similar to a closure or other object passed to an algorithm that iterates over the data structure, where the closure or other object is called for each node and discriminates between the nodes without coupling the object model to the visitor.
In a statically typed language, this was "clever" because if you put an accept() method on each class that calls visitor.visit(this|self|whatever) it makes the compiler enforce that your visitor classes implements a visit() method for each possible node type.
For dynamic languages like Ruby that benefit kind of evaporates, but at the same time runtime type checks are normal, and so yes, you can just use any standard algorithm that iterates over the nodes in your preferred order and pass it a closure or suitable object that .e.g. does "case object.class; when ..." or similar to group the code together instead. If one absolutely wanted to mimic the GoF visitor, one could do 'send("visit_#{object.class.name}".to_sym,object)' or something along those lines to make visitors be classes with methods for each node type instead.
A lot of the GoF patterns are mainly useful in statically typed languages and/or languages lacking first-order functions or closures.
In a statically typed language, this was "clever" because if you put an accept() method on each class that calls visitor.visit(this|self|whatever) it makes the compiler enforce that your visitor classes implements a visit() method for each possible node type.
For dynamic languages like Ruby that benefit kind of evaporates, but at the same time runtime type checks are normal, and so yes, you can just use any standard algorithm that iterates over the nodes in your preferred order and pass it a closure or suitable object that .e.g. does "case object.class; when ..." or similar to group the code together instead. If one absolutely wanted to mimic the GoF visitor, one could do 'send("visit_#{object.class.name}".to_sym,object)' or something along those lines to make visitors be classes with methods for each node type instead.
A lot of the GoF patterns are mainly useful in statically typed languages and/or languages lacking first-order functions or closures.