It all started with a Tweet

Since the other two background threads I have running trying to get some more technical posts together are still running, I had to make the decision to write about something different. I struggled for some time until I saw Christer Ericson. We’ll start with the code shown in that very tweet:

w = u.dot(v)

Taking Scala as our implementation language, there’s a way that can be changed to alleviate one of the issues that people have with that snippet of code and that is to write it like this:

w = u.dot(v)

For the more astute amongst you the sentence “But Sean, you moron, that is just the same.” may be just about to spring forth from your lips. The same characters are there with the same end result where the ‘dot’ method is called on ‘u’ with a parameter of ‘v’, which are both vectors. The difference is in the definition of that method, the original would look exactly as you’d expect:

def dot(vector: Vector): Double = {
 
    (x * vector.x) + (y * vector.y) + (z * vector.z)
 
  }

Now lets look at the code in the Vector class using implicits:

 

There’s nothing wrong with your screens, there is no code for the dot method in the Vector class at all, instead an implicit conversion is used to wrap the given class in another which has that method on it. Here’s the code which drives the implicits example:

 object ImplicitConversions {
 
    implicit def vectorToMath(vector: Vector) = new VectorMath(vector)
 
  }
 
  case class VectorMath(leftHandSide: Vector) {
 
    def dot(rightHandSide: Vector): Double = (leftHandSide.x * rightHandSide.x) + (leftHandSide.y * rightHandSide.y) + (leftHandSide.z * rightHandSide.z)
 
  }

The VectorMath class in this instance contains the dot method and keeps the logic completely separate to the code of Vector. A similar effect could be created by using a trait that contained the method but that is not possible if you don’t control the instantiation or definition of the class. For example, the classes returned from a library could be implicitly converted into those used in your internal code, without the need to sprinkle ‘toX’ methods everywhere.

Who needs inheritance?

This technique of conversion can be used to create a disjoint union of types, which is to say that without any inheritance related shenanigans a bunch of types are grouped together. Imagine a game where large boxes can be pushed by the player, this new revolutionary feature is going to amaze and wow the world. Some time later a mission has been designed where the player needs to push their car because it has broken down. But the Car and Box classes aren’t interrelated by anything other than a WorldObject parent class and pulling the push method all the way up to there wouldn’t make any sense as a Sky class inherits from it too.

A first thought would be to use a mixin or an interface to make both ‘Pushable’. A mixin wont work as the code needs to be subtly different for each and an implemented interface results in Box inheriting 45 interfaces (the box simulation is incredibly detailed). Implicit conversions come to the rescue with a wrapper class for each case that includes the specific logic for each case, but tightly constrains it only to those classes that can support it:

case class Direction(x: Double, y: Double)
 
  object PushableImplicits {
 
    implicit def carToPushable(car: Car) = new CarPushable(car)
 
    implicit def boxToPushable(box: Box) = new BoxPushable(box)
 
  }
 
  abstract class Pushable[T <: WorldObject] {
 
    def push(direction: Direction): Unit
 
  }
 
  case class CarPushable(val car: Car) extends Pushable[Car] {
 
    def push(direction: Direction): Unit = {
 
      car.x += direction.x
 
      car.y += direction.y
 
    }
 
  }
 
  case class BoxPushable(val box: Box) extends Pushable[Box] {
 
    def push(direction: Direction): Unit = {
 
      // In this game boxes can only be moved along the 2 main axes.
 
      if (direction.x.abs > direction.y.abs) {
 
        box.x += direction.x.toInt
 
      }
 
      else {
 
        box.y += direction.y.toInt
 
      }
 
    }
 
  }

Moar implicits, moar!

Taking the example code above, if the game engine runs in a server and client mode, then the need for a tweak comes in. In server mode, the push method needs to respond with a JSON representation of the before and after, in client mode it will just return the instance directly. Now if only the push operation was all that existed, this could easily be done by adding an extra argument to the method and that’s it. Unfortunately our game engine has 500 different operations, so that parameter will end up everywhere and need adding to both sides of the engine code. However, there is an additional type of implicit, the implicit parameter!
So a few tweaks to the innards of CarPushable and we end up with:

def push[U](direction: Direction)(implicit converter: Converter[Car, U]): BeforeAfter[U] = {
 
    BeforeAfter.captureChanges(car, {() =>
 
      car.x += direction.x
 
      car.y += direction.y
 
      car
 
    })
 
  }

This snippet goes even further to capture the before and after state of our push method in whatever form we require. Two examples of this usage look like this:

println(box.push[JSON](new Direction(-1, 10))) // JSON output for server mode.
 
  println(box.push[Box](new Direction(-1, 10)))  // Objects for client mode.

Typing is enforced for the implicit parameters, with the parameter being required but also unique for whatever combination of types in that scope (probably the most important thing to remember). It has an effect similar to that of dependency injection (or Inversion of Control) frameworks that can autowire by type, except that all the autowiring is done at compile time by the Scala compiler itself.

A great example of what can be done with implicit parameters lies in the Scala collections framework. The map method (used for transforming the contents of a collection) has the following signature:

def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That

As a result of that design, it is defined only once in the TraversableLike trait, but transforming a List results in a List and transforming a Set results in a Set. By defining only a couple of methods and inheriting from the necessary traits makes it possible to define custom collection types that are fully realised and correctly typed.

Until next time.

As with all my posts so far, here is a complete SBT project containing the code mentioned within this post.

Addendum.

As pointed out in the comments, the thing to be careful of with implicit conversions is that they cause an object allocation to occur each time they are used, so two calls to the push method mentioned above will cause two instantiations of the relevant Pushable implementation.