有没有办法干掉这些用默认值转换数字的函数?

时间:2014-06-24 06:47:53

标签: 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
  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
    }

有什么方法可以让这些更干净?除了一行之外,它们基本上都做同样的事情。

3 个答案:

答案 0 :(得分:4)

您可以利用Numeric来避免重复归零。

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

答案 1 :(得分:2)

您可以使用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)

答案 2 :(得分:1)

虽然克里斯·马丁的答案可能是最复杂的,但却相当复杂。你可以封装"尝试一些东西,或者让我得到默认的"通过使用返回函数的函数。

 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返回一个函数,该函数在抛出异常的情况下执行String的转换。

您可以将此converter用于任何可能引发异常的转化,而不只是数字值。