Scala包装器,用于流畅的副作用

时间:2015-10-29 08:52:59

标签: scala

我正在寻找scala中的东西,以更紧凑的方式编写以下代码:

def getSomething():X = {
  val result = compute(...)
  println(result)
  result
}

我在想这样的事情:

def getSomething():X = {
  MagicWrapper(compute(...)).do(println)
}

这样执行do但返回原始值。听起来像这样的事情应该存在于某个地方,但我找不到任何东西。

1 个答案:

答案 0 :(得分:3)

使用extend-my-library模式:

implicit class SideEffectPassthrough[A](val a: A) extends AnyVal {
  def se(sideEffectFunction: A => Unit): A = {
    sideEffectFunction(a)
    a
  }
}

def compute(a: Int) = a + 2 + 3
val x = compute(1).se(println)
// x: Int = 6

编译器将为您执行包装,使语法更清晰。 (但是,请注意,当我们添加extends AnyVal时,我们实际上确保编译器将重写此代码,以便它不会直接执行任何包装;相反,它将创建一个静态函数来处理行为,这意味着减少运行时间开销,因为不需要实例化包装器对象。)

sideEffectFunction的{​​{1}}参数可以是任意函数,只要它的参数为前面表达式的结果:

se

为了完整起见,这是实现同一目标的另一种方式:

val y = compute(1).se { r =>
  println("Performing a side effect now!")
  println(r)
}
// y: Int = 6

参数def printAndReturn[A](block: => A): A = { val result = block println(result) result } val x = printAndReturn(1+2+3) // x: Int = 6 val y = printAndReturn { val a = 1 + 2 a + 3 } // y: Int = 6 可以是任意表达式,包括任意代码块。请注意,它是按名称传递的,因此在block内进行评估。