【问题标题】:How to pattern-match against every numeric class in one case?如何在一种情况下对每个数字类进行模式匹配?
【发布时间】:2013-11-03 19:31:58
【问题描述】:

假设我有

def foo(x: Any) = x match {
  case s: String => println(0)
  case i: Int => println(1)
  case l: Long => println(2)
  //...
}

有什么办法可以做出类似下面的东西吗?

def foo(x: Any) = x match {
  case s: String => println(0)
  case i: Numeric => println("Numeric")
}

【问题讨论】:

    标签: scala pattern-matching


    【解决方案1】:

    你可以匹配Number接口:

    def foo(x: Any) = x match {
      case s: String => println(0)
      case i: java.lang.Number => println("Numeric")
    }
    

    【讨论】:

    • 不鼓励这种匹配,因为它是类型转换的同义词,这是可能的,但在函数式编程中被认为是“糟糕的风格”。
    • 嗯,没有惯用的方法,所以在这种情况下,这是相当鼓励的——直到 Scala 赶上 Java..
    【解决方案2】:

    你可以试试这个:

    def foo[A](x: A)(implicit num: Numeric[A] = null) = Option(num) match {
      case Some(num) => println("Numeric: " + x.getClass.getName)
      case None => println(0)
    }
    

    那么这个

    foo(1)
    foo(2.0)
    foo(BigDecimal(3))
    foo('c')
    foo("no")
    

    将打印

    Numeric: java.lang.Integer
    Numeric: java.lang.Double
    Numeric: scala.math.BigDecimal
    Numeric: java.lang.Character
    0
    

    请注意,获得null 隐式参数并不意味着不存在这样的隐式参数,而只是在编译时在隐式搜索范围内没有找到。

    【讨论】:

    • 这是一个棘手的问题!可惜我不能同时接受这两个答案。
    • 有没有(好的)方法来避免null 值? (例如,提供隐含的Option[Numeric[A]]?)
    • 我能想到的所有技巧都将大大降低可读性并且不会更安全。
    • 这就是我的怀疑。感谢您的澄清!
    • 我注意到如果将数值输入为 Any 然后传递给方法,则此解决方案不起作用,例如val x: Any = 3.14; foo(x) 将打印 0。在这种情况下,只有接受答案的解决方案才能按预期工作。我需要这个功能,因为我想从Map[String, Any] 中提取任何数值为double。有什么方法可以改变这个方法来使用Any吗?我更喜欢使用Numeric 而不是模式匹配java.lang.Number
    猜你喜欢
    • 1970-01-01
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多