0

我想知道这是否可以使用 Scala 的类型系统来完成。

基本上,我想创建一个接受 aresult类型Try[T]并打印出一条消息的日志记录方法,该消息取决于result是 aSuccess还是 aFailure

例如,签名可能看起来像

def logTry[T](what: Try[T], block: T => String): Unit

并且可以这样使用:

val size: Try[(Int, Int)] = Try(getSizeAndTimestampFromDatabase())
logTry(size, e => "size is " + e._2 + " kb")

这将输出

size is 13 kb如果sizeSuccess(x: Int),例如,Success(13)

或者

error: size is (not available)如果size如果类型Failure(t: Throwable)

棘手的部分是,如果它是 a ,我们需要能够访问Try用于打印到屏幕的对象,或者如果它是 a作为占位符Success,则打印选择的默认字符串(例如“(不可用)”) 。Failure此外,它必须使用非常通用的类型,T或者Any范围可以从简单的标量值到类的实例等。

这个古怪函数的用例是,它可以非常方便地以一种信息丰富的方式记录 Try 对象,而不会用 map/recover 或 match 语句使代码混乱。

这是我想出的骨架,当然最难的部分还没有弄清楚。

def logTry[T](what: Try[T], block: T => String): Unit = {
  what match {
    case Success(res) => println(block(res))
    case Failure(t) => println(???) // how to do this
  }
}
4

2 回答 2

0

这就是我要做的(好吧,如果我不使用隐式将方法添加到Try):

def logTry[T](t: Try[T])(f: Try[T] => String) { println(f(t)) }

val size: Try[Integer] = Try(getSizeFromDatabase())
logTry(size) {
    case Success(e) => s"size is $e kb"
    case Failure(e) => s"error: size is (${e.getMessage}})"
}

编辑:了解您的要求后

def logTry(t: Try[Any], f: Any => String) {
    t match {
        case Success(e) => println(f(e))
        case Failure(e) => println(f(new Object {
            override def toString = "(not available)"
        }))
    }
}

val size: Try[Integer] = Try(getSizeFromDatabase())
logTry(size, s => s"Size is $s kb")

我不知道实现泛型类型 T 的方法,但无论如何我认为这不是一个好主意:客户端可以在打印时特别使用 T 的方法,但你希望它总是在应该从 T 打印信息的地方打印“不可用”,这并不是那么简单。

另一种选择是创建一个特殊的格式化程序(think "size is ${...} kb"),以便记录器知道如何替换它,但我不确定这是否是你想要的。

于 2015-05-19T10:00:32.370 回答
0

这里的解决方案不强制您明确提供类型:

implicit class LogTry[T](attempt: Try[T]) {
  def log[E](comp: T => E, block: String => String, error: Throwable => String = _ => "(N/A)") =
    println(block(attempt map (comp andThen (_.toString)) recover { case ex => error(ex) } get))
}

用它作为

size.log(_._2, size => f"size is $size kb")

或者

size.log(_._2, size => f"size is $size kb", err => f"(not available because $err)")
于 2015-05-19T10:02:11.787 回答