Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala empty default closure?

just a quick question I seem to be unable to find an answer to.

I have a method definition in Scala that looks like this:

def execute(goals: List[String],
            profiles: List[String] = List(),
            loggingCallback: (String) => Unit = { _ => }): Result = {
    // method body
    loggingCallback("a message")
}

I would like to know whether there is a better way to specify a default empty closure. The question is not about how to implement logging, this is just an example.

like image 771
Andreas Eisele Avatar asked Dec 08 '10 12:12

Andreas Eisele


2 Answers

Your solution is fine. You could introduce a type alias for Function1[X, Unit]; use () as per Kevin's answer, and drop unnecessary parens.

scala> type Effect[-A] = (A => Unit)
defined type alias Effect

scala> def foo(f: Effect[String] = _ => ()) = ()
foo: (f: (String) => Unit)Unit

You could also define a noop function:

scala> val noop = (a: Any) => ()
noop: (Any) => Unit = <function1>

scala> def foo(f: Effect[String] = noop) = ()
like image 154
retronym Avatar answered Nov 17 '22 23:11

retronym


The value () is an instance of unit, so this should do the trick:

def execute(
  goals: List[String],
  profiles: List[String] = Nil,
  loggingCallback: (String) => Unit = { _ => () }): Result =
{
  // method body
  loggingCallback("a message")
  // do something returning a Result
}

update

If something is optional, then it often makes more sense to state so explicitly, this also results in better self-documenting code:

def execute(
  goals: List[String],
  profiles: List[String] = Nil,
  loggingCallback: Option[(String) => Unit] = None): Result =
{
  // method body
  loggingCallback forEach { _.apply("a message") }
  // do something returning a Result
}

update 2

DSL-esque situations like this are also one of the very few situations where I'll condone the use of null in Scala:

def execute(
  goals: List[String],
  profiles: List[String] = Nil,
  loggingCallback: (String) => Unit = null
): Result = {
  // method body
  val log = Option(loggingCallback) getOrElse {_ => ()}
  log("a message")
  // do something returning a Result
}

Note the Option(loggingCallback) to immediately convert the nullable loggingCallback into a nice type-safe Option, then getOrElse to provide a fallback alternative.

like image 8
Kevin Wright Avatar answered Nov 18 '22 00:11

Kevin Wright