Пустое закрытие Scala по умолчанию?

просто быстрый вопрос, на который я, кажется, не могу найти ответ.

У меня есть определение метода в Scala, которое выглядит так:

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

Я хотел бы знать, есть ли лучший способ указать пустое закрытие по умолчанию. Вопрос не в том, как реализовать логирование, это просто пример.


person Andreas Eisele    schedule 08.12.2010    source источник
comment
Что не так с тем, как вы это сделали? Это довольно лаконично!   -  person oxbow_lakes    schedule 08.12.2010
comment
Я не говорю, что что-то не так с тем, как я это указал. Чего я только не знаю, так это того, является ли эта спецификация достаточной и/или хорошим стилем.   -  person Andreas Eisele    schedule 08.12.2010


Ответы (2)


Ваше решение в порядке. Вы можете ввести псевдоним типа для Function1[X, Unit]; используйте () в соответствии с ответом Кевина и удалите ненужные скобки.

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

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

Вы также можете определить функцию noop:

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

scala> def foo(f: Effect[String] = noop) = ()
person retronym    schedule 08.12.2010

Значение () является экземпляром единицы, так что это должно сработать:

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

обновить

Если что-то является необязательным, то часто имеет смысл указать это явно, это также приводит к лучшему самодокументированному коду:

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
}

обновление 2

Подобные ситуации в стиле DSL также являются одной из очень немногих ситуаций, когда я одобряю использование null в 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
}

Обратите внимание, что Option(loggingCallback) используется для немедленного преобразования loggingCallback, допускающего значение NULL, в красивое типобезопасное Option, а затем getOrElse для обеспечения резервной альтернативы.

person Kevin Wright    schedule 08.12.2010
comment
Вы правы, использование Option здесь делает вещи более понятными для вызывающих абонентов. - person Andreas Eisele; 09.12.2010