0

我经常有这样的功能:

{
  val x = foo;
  bar(x);
  x
}

例如,bar通常是Log.debug.

有没有更短的、惯用的方式来运行它?例如,像这样的内置函数

def act[A](value: A, f: A => Any): A = { f(value); value }

这样我就可以写了act(foo, bar _)

4

3 回答 3

1

我不确定我是否正确理解了这个问题,但如果我理解了,那么我经常使用从 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)
}
于 2013-07-10T14:06:20.857 回答
1

使用你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课堂上添加您喜欢的任何其他常用水龙头。

于 2013-07-10T14:56:07.540 回答
0

请注意,Scala 已经包含了一个语法重量级的版本:

foo match { case x => bar(x); x }

但是创建较短的版本(tap在 Ruby 中——我建议使用相同的名称)可能有优势。

于 2013-07-10T15:11:38.850 回答