Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternatives to multimethods in Scala or Jython

Tags:

jython

scala

I often face the problem of wanting to add additional methods to classes I don't control. For instance, I might want to have a function prettyPrint that can operate on different object types that do not have a unified api (e.g. special __str__ methods).

The Nice language and R accomplishes this using multimethods, which avoid the Visitor Pattern nicely. For instance, R has the plot() function. Individual programmers can create new classes to define data types (e.g., network graphs or stock ticker data). A secondary user/programmer could then write a plot function to fill out the functionality, even though they don't have access to the graph or stock ticker code, or the code of other plot functions.

Given that I would like to add lots of functionality later, using class.method() seems infeasible. Lots of class_plot() functions for each type also seems like a bad idea. Defining one big plot() function that checks types isn't extensible.

What are alternatives to multimethods? In particular, I'm interested in designs that might work in Jython and Scala.

like image 769
Tristan Avatar asked Dec 30 '22 16:12

Tristan


1 Answers

Easiest way to add a method to a class in Scala:

implicit def defSum(l: List[Double]): Double = new AnyRef { def sum = l.foldLeft(0.0)(_ + _) }

Or, on Scala 2.8, with the particular case of a method handling numbers,

implicit def defSum[T](l: List[T])(implicit n: Numeric[T]) = new AnyRef {
  import n.mkNumericOps
  def sum = l.foldLeft(n.zero)(_ + _)
}

Only this isn't needed on Scala 2.8, because it defines sum already.

You can also add traits when instantiating:

// Immutable class
case class Point(x: Int, y: Int)

// Somewhere else in the code    
trait MyPlot {
  self: Point =>
  import self._

  def plot = println("At "+x+", "+y)
}

// Usage
val p = new Point(1,2) with MyPlot
p.plot

What you cannot do is add a method dynamically (ie, at run-time instead of compile-time) to an object. In the first case, you are saying "add this method to this class". On the second case you are saying "create this object with this trait". These are ok, but "add this method to this object" is not.

like image 60
Daniel C. Sobral Avatar answered Jan 01 '23 05:01

Daniel C. Sobral