Aug 092012
 

Stackable traits in Scala refers to being able to mix in multiple traits that work together to apply multiple modifications to a method. This involves invoking super.theMethod and modifying its input and/or output. But what is super in the context of a trait? The class (or trait) the trait extends from? The class the trait is being mixed into? It depends! All the mixed in traits and all the superclasses are linearized. super invokes the nearest preceding definition further up the chain. The general effect is that mixins to the right (and their ancestor classes) come earlier than those to the left. However, ancestors that are shared are deduped to only show up once, and they show up as late as possible. Here’s a detailed description of the Scala object hierarchy linearization algorithm.

If a trait which extends MyInterface tries to invoke super.myMethod but MyInterface.myMethod is abstract, the compiler generates this error:

error: method myMethod in trait MyInterface is accessed from super. It may not be abstract unless it is overridden by a member declared `abstract' and `override'

What this means is: generally, invoking an abstract method of a superclass is an error. However, with traits, the meaning of super is not known at compile time. The call would be valid if the trait were mixed into a class that had an implementation of the method. But the compiler errs on the side of caution unless told otherwise. abstract override def myMethod provides signals that you expect an implementation of the method to be available at run-time and to not treat the super.myMethod invocation as an error. (Note: this applies regardless of whether the trait itself provides an implementation of the method.)

Here are some examples:

trait Munger {
  def munge(l : List[String]) : List[String]
}

trait Replace1 extends Munger {
  override def munge(l : List[String]) = l :+ "Replace1"
}

trait Replace2 extends Munger {
  override def munge(l : List[String]) = l :+ "Replace2"
}

//abstract override def munge required in the Stack* classes because they invoke
//abstract super.munge

trait Stack1 extends Munger {
  abstract override def munge(l : List[String]) = super.munge(l) :+ "Stack1"
}

trait Stack2Parent extends Munger
  abstract override def munge(l : List[String]) = super.munge(l) :+ "Stack2Parent"
}

trait Stack2 extends Stack2Parent {
  abstract override def munge(l : List[String]) = super.munge(l) :+ "Stack2"
}

class Bottom {
  this : Munger =>

  def apply() {
    println(
      munge(List("bottom"))
    )
  }
}

scala> (new Bottom with Replace1)()
List(bottom, Replace1)

scala> (new Bottom with Replace1 with Replace2)()
List(bottom, Replace2) //Replace1's munge was overridden and never ran

scala> (new Bottom with Replace1 with Stack1)()
List(bottom, Replace1, Stack1) //Stack1 called super.munge, which invoked the
//munge from the trait to the left

scala> (new Bottom with Replace1 with Stack2)()
List(bottom, Replace1, Stack2Parent, Stack2) //Stack2's super.munge called to its
//superclass, whereas Stack2Parent's super.munge called the trait to the left
Nov 172011
 

[ERROR] error: File name too long

A common way to install Ubuntu is with an underlying ext4 file system and eCryptfs encrypted home directories. ext4, like many other file systems, has a maximum filename limit of 255 bytes. eCryptfs creates filenames much longer than the original. Compiled Scala classes tend to have long file names since anonymous classes end up in their own files. Therefore, when compiling Scala projects within eCryptfs on ext4, it is easy to get file name too long errors. :-(

Oct 042011
 

Ruby, Python, and many other dynamic languages have a so-called splat operator that lets you easily invoke a function by providing a list of argument values:

def f(x,y)
  x*y
end

> fArgs = [6,7.0]
=> [6, 7.0]

> f(*fArgs)
=> 42.0

Scala does not have a splat operator per se, but you can achieve the same effect without too much work. Sadly the syntax is different for fixed-arity and variadic functions.

Scala splat for variadic functions

For variadic functions there effectively is a splat operator. If you invoke a variadic function and append :_* to the argument the compiler will perform the splat:

> def g(xs:Int*) = (0 /: xs) (_ + _)
g: (xs: Int*)Int

> val gArgs = List(1,2,3,4)
gArgs: List[Int] = List(1, 2, 3, 4)

> g(gArgs:_*)
res23: Int = 10

Scala splat for fixed-arity functions

> def f(x:Int, y:Double) = x * y
f: (x: Int, y: Double)Double

> val fArgs = (6, 7.0)
fArgs: (Int, Double) = (6,7.0)

> f _ tupled fArgs
res8: Double = 42.0

Magic! The first part, f _, is the syntax for a partially applied function in which none of the arguments have been specified. This works as a mechanism to get a hold of the function object. tupled returns a new function which of arity-1 that takes a single arity-n tuple. It is defined in the Scala Function object,

However, given a List of arguments to pass to f, I’m not sure how to easily convert the List to a Tuple.

p.s. There’s a stackoverflow post about this called “scala tuple unpacking.”

Jun 052011
 

Quick refresher: self-types are commonly used when writing traits that want to proscribe that they get mixed in to a particular class. For example, the cake-pattern leverages them. In the example below, FooTrait specifies a self-type of FooTraitConfiguration to insure that it is mixed in to a class that provides the expected times val.

import actors.Actor
import actors.Actor._

trait FooTraitConfiguration { val times : Int }

trait FooTrait { self:FooTraitConfiguration =>
  case object Ping
  case object Pong

  val a = actor {
    loop {
      react {
        case Ping =>
          self ! Pong
        case Pong =>
          for(_ <- (1 to times)) { print(".") }
          System.out.println("pong.")
  } } }

  def ping = a ! Ping
  def pong = a ! Pong
}

class Foo extends FooTrait with FooTraitConfiguration { @Override val times = 5 }

But, alas, this fails to compile:

error: value ! is not a member of FooTrait with FooTraitConfiguration
self ! Pong

It seems that the self-trait has broken the Actor API! And indeed, it has. Because self-traits are not usually specified with self! It should have been:
this:FooTraitConfiguration =>

The self-type means that within FooTrait the type of this is considered to be FooTrait with FooTraitConfiguration. Using a word other than this additionally sets up an alias to that type for e.g. use within nested classes. And there’s the rub: Actors depend on a method named self which is shadowed when the alias to the type is named self.

Note to self: Don’t use self when specifying self types!