---
title: "Visitor pattern and double dispatch in ruby"
description:
  "Visitor pattern is a common pattern to traverse a tree.  This blog discusses
  what visitor pattern is and how to write code for that in ruby."
canonical_url: "https://www.bigbinary.com/blog/visitor-pattern-and-double-dispatch"
markdown_url: "https://www.bigbinary.com/blog/visitor-pattern-and-double-dispatch.md"
---

# Visitor pattern and double dispatch in ruby

Visitor pattern is a common pattern to traverse a tree. This blog discusses what
visitor pattern is and how to write code for that in ruby.

- Author: Neeraj Singh
- Published: July 7, 2013
- Categories: Rails

Let's say that we have an AST that holds integer nodes. We want to print double
the value of all nodes. We can do something like this

```ruby
class IntegerNode
  def initialize(value)
    @value = value
  end

  def double
    @value * 2
  end
end

class Ast
  def initialize
    @nodes = []
    @nodes << IntegerNode.new(2)
    @nodes << IntegerNode.new(3)
  end

  def print_double
    @nodes.each do |node|
      puts node.double
    end
  end
end

ast = Ast.new
ast.print_double # => 4 6
```

Above solution works. Now let's try to print triple the value. In order to do
that we need to change class `IntegerNode`. And `IntegerNode` has knowledge of
how to print `triple` value. Tomorrow if we have another node called `FloatNode`
then that node will have knowledge about how to `double` and `triple` the value.

Nodes are merely storing information. And the representation of data should be
separate from the data itself. So `IntegerNode` and `FloatNode` should not know
about how to `double` and `triple`.

To take the data representation code out of nodes we can make use of
[visitor pattern](http://en.wikipedia.org/wiki/Visitor_pattern) . Visitor
pattern uses [double dispatch](http://en.wikipedia.org/wiki/Double_dispatch) .

Before we look at "double dispatch" let's first look at "single dispatch".

## Single dispatch

When we invoke a method in ruby we are using single dispatch. In single
dispatch, method invocation is done based on a single criteria: class of the
object. Most of the object oriented programming languages use `single dispatch`
system.

In the following case method `double` is invoked solely based on the class of
`node`.

```ruby
node.double
```

## Double dispatch

As the name suggests in the case of `Double dispatch` dispatching depends on two
things: class of the object and the class of the input object.

Ruby inherently does not support "Double dispatch". We will see how to get
around that issue shortly. First let's see an example in Java which support
Double dispatch. Java supports `method overloading` which allows two methods
with same name to differ only in the type of argument it receives.

```java
class Node
   def double(Integer value); value *2; end
   def double(String value); Integer.parseInt(value) * 2; end
end

node.double(2)
node.double("51")
```

In the above case the method that would be invoked is decided based on two
things: class of the object ( node ) and the class of the value (Integer or
String). That's why this is called `Double dispatch`.

In ruby we can't have two methods with same name and different signature because
the second method would override the first method. In order to get around that
limitation usually the method name has class name. Let's try to write above java
code in ruby.

```ruby
class Node
  def accept value
   method_name = "visit_#{value.class}"
   send method_name
  end

  def visit_Integer value
   value * 2
  end

  def visit_String value
    value.to_i * 2
  end
end
```

If the above code is not very clear then don't worry. We are going to look at
visitor pattern in ruby and that will make the above code clearer.

## Visitor pattern

Now let's get back to the problem of traversing the AST. This time we are going
to use "Double dispatch" so that node information is separate from
representation information.

In visitor pattern `nodes` define a method called `accept`. That method accepts
the visitor and then that method calls `visit` on visitor passing itself as
self.

Below is a concrete example of visitor pattern. You can see that `IntegerNode`
has method `accepts` which takes an instance of `visitor` as argument. And then
`visit` method of visitor is invoked.

```ruby
class Node
  def accept visitor
    raise NotImpelementedError.new
  end
end

module Visitable
  def accept visitor
    visitor.visit self
  end
end

class IntegerNode < Node
  include Visitable

  attr_reader :value
  def initialize value
    @value = value
  end
end

class Ast < Node
  def initialize
    @nodes = []
    @nodes << IntegerNode.new(2)
    @nodes << IntegerNode.new(3)
  end

  def accept visitor
    @nodes.each do |node|
      node.accept visitor
    end
  end
end

class DoublerVisitor
  def visit subject
    puts subject.value * 2
  end
end

class TriplerVisitor
  def visit subject
    puts subject.value * 3
  end
end

ast = Ast.new
puts "Doubler:"
ast.accept DoublerVisitor.new
puts "Tripler:"
ast.accept TriplerVisitor.new

# =>
Doubler:
4
6
Tripler:
6
9
```

Above code used only `IntegerNode`. In the next example I have added
`StringNode`. Now notice how the `visit` method changed. Now based on the class
of the argument the method to dispatch is being decided.

```ruby
class Node
  def accept visitor
    raise NotImpelementedError.new
  end
end

module Visitable
  def accept visitor
    visitor.visit(self)
  end
end

class IntegerNode < Node
  include Visitable

  attr_reader :value
  def initialize value
    @value = value
  end
end

class StringNode < Node
  include Visitable

  attr_reader :value
  def initialize value
    @value = value
  end
end

class Ast < Node
  def initialize
    @nodes = []
    @nodes << IntegerNode.new(2)
    @nodes << StringNode.new("3")
  end

  def accept visitor
    @nodes.each do |node|
      node.accept visitor
    end
  end
end

class BaseVisitor
  def visit subject
    method_name = "visit_#{subject.class}".intern
    send(method_name, subject )
  end
end

class DoublerVisitor < BaseVisitor
  def visit_IntegerNode subject
    puts subject.value * 2
  end

  def visit_StringNode subject
    puts subject.value.to_i * 2
  end
end

class TriplerVisitor < BaseVisitor
  def visit_IntegerNode subject
    puts subject.value * 3
  end

  def visit_StringNode subject
    puts subject.value.to_i * 3
  end
end

ast = Ast.new
puts "Doubler:"
ast.accept DoublerVisitor.new
puts "Tripler:"
ast.accept TriplerVisitor.new

# =>
Doubler:
4
6
Tripler:
6
9
```

## Real world usage

[Arel](https://github.com/rails/arel) uses visitor pattern to build query
tailored to the specific database. You can see that it has a visitor class for
[sqlite3](https://github.com/rails/rails/blob/master/activerecord/lib/arel/visitors/sqlite.rb),
[mysql](https://github.com/rails/rails/blob/master/activerecord/lib/arel/visitors/mysql.rb)
and
[Postgresql](https://github.com/rails/rails/blob/master/activerecord/lib/arel/visitors/postgresql.rb).

## Links

- [Human page](https://www.bigbinary.com/blog/visitor-pattern-and-double-dispatch)
