>This algorithm is an example of the “visitor pattern.” The term visitor pattern simply means that some object, function or other piece of code is executed once for each node in some data structure, such as an array, linked list or tree.
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.
A part of what programming/comp-sci deals with is rapidly changing and somewhat disconnected nomenclature. In the 90's, you may well have been "corrected" that it's the Gang of Four Visitor pattern. Map-reduce, if that's what you're referring to, didn't become popularized until later.
Again, Alan Kay is right -- computer programming is "half a field" that often forgets its own content. Ironically, programming patterns were actually forwarded as a form of technical literature for the programming field, not so much as an approved cookbook.
Not quite, the visitor pattern is a weird kind of map, that avoids specifying the exact type of arguments to the function. This article doesn't do a great job of explaining it. https://en.wikipedia.org/wiki/Visitor_pattern
Yes, that description of the visitor pattern seems wrong to me. The visitor pattern isn't about operating on the elements of collections, it's about altering behavior depending on the type of object being operated on.
The point is that in a statically typed language, the specific approach advocated by the visitor pattern gets compiler assistance to ensure the visitors are complete (at least in the sense that there is a visit() method for each node type). This coupled with limited, difficult to use, or expensive runtime type information in many static languages made it attractive.
In a dynamically typed language where checking if an object is of a specific class, and where you can do if-then or switch(case/when) to discriminate the node types easily, the visitor pattern kind-of devolves into pretty much nothing, and hence the description doesn't "sound" right because it misses out on most of what makes the Visitor pattern worthwhile to discuss as a pattern in e.g. C++ or Java.
Instead of e.g. implementing an "accept" method for each node that calls "visit" on a visitor, and implementing a "Visitor" interface and inheriting from that, in Ruby you might instead just opt to use a case/when structure for the visitor, and wrap it in a single method or a lambda if you need to pass it around.
More generally, the visitor pattern is an example of double dispatch, where the concrete implementation of a function varies on the type of two parameters to the function. I'm not sure that there's any real difference in the implementation of the visitor pattern that arises from static vs dynamic typing. Just like in ruby, in a language like java you could have a cascade of if/elses that type check the second parameter (or the first one for that matter, OO is really just a way to have a case statement that isn't centralized in one place in source code).
But in the GoF visitor pattern, the "case statement" is in fact centralized in one place: In the class implementing the visitor.
And of course you can have the equivalent in C++/Java and similar languages, but that would lose the main benefit of having the completeness of the visitor statically checked (In other words, you can write dynamically typed code in any language some way or the).
Hm. Isn't that a (map)?