我经常有这样的功能:
{
val x = foo;
bar(x);
x
}
例如,bar
通常是Log.debug
.
有没有更短的、惯用的方式来运行它?例如,像这样的内置函数
def act[A](value: A, f: A => Any): A = { f(value); value }
这样我就可以写了act(foo, bar _)
。
我不确定我是否正确理解了这个问题,但如果我理解了,那么我经常使用从 Spray 工具包中获取的这种方法:
def make[A, B](obj: A)(f: A => B): A = { f(obj); obj }
然后你可以写以下内容:
utils.make(new JobDataMap()) { map =>
map.put("phone", m.phone)
map.put("medicine", m.medicine.name)
map.put("code", utils.genCode)
}
使用你act
写的函数对我来说似乎非常地道。我不知道有什么内置的方法可以做到这一点,但我只是把这种东西放在我到处使用的“commons”或“utils”项目中。
如果 bar 函数通常是相同的(例如 Log.debug),那么您也可以为此创建一个特定的包装函数。例如:
def withDebug[A](prefix: String)(value: A)(implicit logger: Logger): A = {
logger.debug(prefix + value)
value
}
然后您可以按如下方式使用它:
implicit val loggerI = logger
def actExample() {
// original method
val c = act(2 + 2, logger.debug)
// a little cleaner?
val d = withDebug("The sum is: ") {
2 + 2
}
}
或者更多的语法糖:
object Tap {
implicit def toTap[A](value: A): Tap[A] = new Tap(value)
}
class Tap[A](value: A) {
def tap(f: A => Any): A = {
f(value)
value
}
def report(prefix: String)(implicit logger: Logger): A = {
logger.debug(prefix + value)
value
}
}
object TapExample extends Logging {
import Tap._
implicit val loggerI = logger
val c = 2 + 2 tap { x => logger.debug("The sum is: " + x) }
val d = 2 + 2 report "The sum is: "
assert(d == 4)
}
Wheretap
需要一个任意函数,并且report
只包装一个记录器。当然,您可以在Tap
课堂上添加您喜欢的任何其他常用水龙头。
请注意,Scala 已经包含了一个语法重量级的版本:
foo match { case x => bar(x); x }
但是创建较短的版本(tap
在 Ruby 中——我建议使用相同的名称)可能有优势。