Scala 有什么方法可以使这些用默认值转换数字的函数干涸?
我有很多这样的功能:Scala 有什么方法可以使这些用默认值转换数字的函数干涸?,scala,dry,Scala,Dry,我有很多这样的功能: // Convert a string to integer, defaulting to 0 if it fails def safeToInt(s: String): Int = try { s.toInt } catch { case _: NumberFormatException => 0 } // Convert a string to long, defaulting to 0 if it fails
// Convert a string to integer, defaulting to 0 if it fails
def safeToInt(s: String): Int = try {
s.toInt
} catch {
case _: NumberFormatException => 0
}
// Convert a string to long, defaulting to 0 if it fails
def safeToLong(s: String): Long = try {
s.toLong
} catch {
case _: NumberFormatException => 0
}
// Convert a string to double, defaulting to 0 if it fails
def safeToDouble(s: String): Double = try {
s.toDouble
} catch {
case _: NumberFormatException => 0
}
有没有办法让这些更干净?除了一行之外,它们基本上都做相同的事情。您可以利用
数值来避免重复零
import scala.util.Try
def safeToNumeric[A: Numeric](f: String => A)(s: String): A =
Try(f(s)).getOrElse(implicitly[Numeric[A]].zero)
val safeToInt = safeToNumeric(_.toInt)(_)
val safeToLong = safeToNumeric(_.toLong)(_)
val safeToDouble = safeToNumeric(_.toDouble)(_)
safeToInt("4") // 4
safeToDouble("a") // 0.0
不幸的是,Numeric
也没有提供解析方法,但是您可以自己创建适当的类型类
case class Parser[A](parse : String => A)
implicit val intParser = Parser(_.toInt)
implicit val longParser = Parser(_.toLong)
implicit val doubleParser = Parser(_.toDouble)
。。。然后您可以编写一个适用于所有类型的方法
def safeTo[A: Parser : Numeric](s: String): A =
Try(implicitly[Parser[A]].parse(s))
.getOrElse(implicitly[Numeric[A]].zero)
safeTo[Int]("4") // 4
safeTo[Double]("a") // 0.0
您可以使用scala.util.Try
import util.Try
// Convert a string to integer, defaulting to 0 if it fails
def safeToInt(s: String): Int = Try(s.toInt).getOrElse(0)
// Convert a string to long, defaulting to 0 if it fails
def safeToLong(s: String): Long = Try(s.toLong).getOrElse(0L)
// Convert a string to double, defaulting to 0 if it fails
def safeToDouble(s: String): Double = Try(s.toDouble).getOrElse(0.0)
尽管克里斯·马丁的答案可能是最复杂的,但它相当复杂。您可以通过使用返回函数的函数来封装“try something,or get me the default”
import scala.util.Try
def safeConverter[A](convert: String => A, default: A) = { input: String =>
Try(convert(input)).getOrElse(default)
}
val safeToInt = safeConverter(_.toInt, 0)
val safeToLong = safeConverter(_.toLong, 0L)
val safeToDouble = safeConverter(_.toDouble, 0.0)
safeToInt("334") // Returns 334
safeToInt("this is not a number") // Returns 0
converter
返回一个函数,该函数在引发异常时使用默认值对字符串进行转换
您可以将此转换器
用于可能引发异常的任何转换,而不仅仅是数值。虽然在技术上很有趣,但我想知道该解决方案增加的复杂性如何与@don mackenzie提出的简单三行相比。一句简单的话:提高代码的可维护性。我想我并不认为它有那么有趣或复杂。为什么这么复杂?因为它使用上下文边界?因为LoC更高?因为得到的方法更抽象?这不是意图的最直接表达吗?[x]以上所有内容。