SAM closures are a way to create an implementation for an interface with a single method easily.

 

In Java, creation of such interfaces requires the use of annonymous classes.

 

In Scala, we have functions.

 

But first, why create a single method interface if you can use a function? Well, there are two reasons I can think of:

  1. Typing: if a method accepts an argument of type SAM, then it is is easy to see who extends this type with concrete implementations.
  2. It allows to add more methods to the interface later on. Sometimes a new feature requires adding a method (maybe overloading) to the interface

 

Here is how one can simulate SAM closures in Scala:

In SAM.scala

trait SAM {
  def meth(s: String): String
}

object SAM {
  implicit def fn2SAM(fn: String => String) = new SAM {
    def meth(s: String) = fn(s)
  }
}


Then somewher else:

class Service {
  def example(sam: SAM) = sam("hi")
}

Now we want to call Service#example with a function:

service.example{s: String => s * 2}

 

What is happening here is this:

  • The compiler sees that example is called with an argument String => String
  • But it expecs a SAM instance
  • So the compiler searches for an implicit conversion in scope and in companion objects of related types (in this case Function1 and SAM)
  • It finds the conversion in the object SAM and applies it.

 

The main benefit here is that in order to call service.example{s: String => s * 2} ther is no need to import SAM. Just Service, the compiler figures out the rest. So usage is nice

 

So this is all well for our own defined types. But what if I want to use predefined types? E.g., I want to use Java's Callable?

 

We can create a SAM type wrapper. Here I use the type 'SAM' again:

trait SAM[T] {
  def inst: T
}

object SAM {
  implicit def fn2SamCallable[T](fn: () => T) = new SAM[Callable[T]] {
    def inst = new Callable[T] {
      def call = fn()
    }
  }
} 

def example(sam: SAM[Callable[String]]) = sam.inst.call

example{() => "hi"}

 

So by wrapping arguments with SAM type decorator we allow the use of functions in place of 3rd party interfaces. (In general the example can implement passing sam.inst to an java.util.concurrent Executor)

 

What if we don't want the wrapping? Or if we want to use a 3rd party method that accepts the interface?

 

Unfortunately, that's as far as type inference will go. If we want our example method to accept arguments of the interface directly (def example[T](callable: Callable[T]) = ...) then the compiler will not search for companion objects of the involved types (e.g., convert a function to Callable[OurType]). In this case, we're left with requiring the client code to import an implicit conversion into scope, or extend a class that provides it:

 

class Implicits {
  implicit def fn2Callable[T](fn: () => T) = new Callable[T] {
    def call = fn()
  }
}

object Implicits extends Implicits

def example[T](callable: Callable[T]) = callable.call

import Implicits._
example{() => "hi"}

// or
class My extends Implicits {
  def go = example{() => "hi"}
}