加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

登录Scala时如何保持返回值

发布时间:2020-12-16 09:36:00 所属栏目:安全 来源:网络整理
导读:在java编程时,我总是记录输入参数和方法的返回值,但是在scala中,方法的最后一行是返回值。所以我必须做一些像: def myFunc() = { val rs = calcSomeResult() logger.info("result is:" + rs) rs} 为了使它变得容易,我写了一个实用程序: class LogUtil(
在java编程时,我总是记录输入参数和方法的返回值,但是在scala中,方法的最后一行是返回值。所以我必须做一些像:

def myFunc() = {
  val rs = calcSomeResult()
  logger.info("result is:" + rs)
  rs
}

为了使它变得容易,我写了一个实用程序:

class LogUtil(val f: (String) => Unit) {
 def logWithValue[T](msg: String,value: T): T = { f(msg); value }
}

object LogUtil {
  def withValue[T](f: String => Unit): ((String,T) => T) = new LogUtil(f).logWithValue _
}

然后我用它:

val rs = calcSomeResult()
withValue(logger.info)("result is:" + rs,rs)

它将记录该值并返回。它适用于我,但似乎很厉害。因为我是一个老的java程序员,而是新的scala,我不知道在scala中是否有更为惯用的方法来做到这一点。

感谢您的帮助,现在我使用由romusz决定的Kestrel组合器创建一个更好的工具

object LogUtil {
  def kestrel[A](x: A)(f: A => Unit): A = { f(x); x }
  def logV[A](f: String => Unit)(s: String,x: A) = kestrel(x) { y => f(s + ": " + y)}
}

我添加f参数,以便我可以从slf4j传递一个记录器,测试用例是:

class LogUtilSpec extends FlatSpec with ShouldMatchers {
  val logger = LoggerFactory.getLogger(this.getClass())
  import LogUtil._

"LogUtil" should "print log info and keep the value,and the calc for value should only be called once" in {
  def calcValue = { println("calcValue"); 100 } // to confirm it's called only once 
  val v = logV(logger.info)("result is",calcValue)
  v should be === 100
  }
}

解决方法

你要找的是Kestrel组合器(K组合器):Kxy = x。您可以在返回传递给它的值时,进行各种副作用(不仅记录)操作。阅读 https://github.com/raganwald/homoiconic/blob/master/2008-10-29/kestrel.markdown#readme

在Scala中,实现它的最简单的方法是:

def kestrel[A](x: A)(f: A => Unit): A = { f(x); x }

然后可以将打印/记录功能定义为:

def logging[A](x: A) = kestrel(x)(println)
def logging[A](s: String,x: A) = kestrel(x){ y => println(s + ": " + y) }

并使用它像:

logging(1 + 2) + logging(3 + 4)

您的示例功能成为单行:

def myFunc() = logging("result is",calcSomeResult())

如果您喜欢OO符号,可以使用其他答案所示的含义,但是这种方法的问题是,每当您想记录某些东西时,您都将创建一个新对象,如果您经常使用它,可能会导致性能下降。但为了完整,它看起来像这样:

implicit def anyToLogging[A](a: A) = new {
  def log = logging(a)
  def log(msg: String) = logging(msg,a)
}

使用它像:

def myFunc() = calcSomeResult().log("result is")

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读