• 再谈类型匹配


    考虑以下例子,我们试图将输入的List[Double] 和List[String] 区分开:

    // src/main/scala/progscala2/patternmatching/match-types.sc scala> for {
    | x <- Seq(List(5.5,5.6,5.7), List("a", "b"))
    | } yield (x match {
    | case seqd: Seq[Double] => ("seq double", seqd)
    | case seqs: Seq[String] => ("seq string", seqs)
    | case _ => ("unknown!", x)
    | })
    <console>:12: warning: non-variable type argument Double in type pattern
    Seq[Double] (the underlying of Seq[Double]) is unchecked since it is
    eliminated by erasure case seqd: Seq[Double] => ("seq double", seqd)
    <console>:13: warning: non-variable type argument String in type pattern 模式匹配 | 105
    Seq[String] (the underlying of Seq[String]) is unchecked since it is
    eliminated by erasure case seqs: Seq[String] => ("seq string", seqs)
    <console>:13: warning: unreachable code case seqs: Seq[String] => ("seq string", seqs)
    res0: List[(String, List[Any])] = List((seq double,List(5.5, 5.6, 5.7)),(seq double,List(a, b)))
    这些警告表示什么?

    Scala 运行于 JVM 中,这些警告来源于 JVM 的类型擦除,类型擦除是Java 5引入泛型后的一个历史遗留。为了避免与旧版本代码断代,JVM的字节码不会记住一个泛型实例(如List)中实际传入的类型参数的信息。所以,当编译器只能识别输入对象为 List,但无法在运行时识别它是 List[Double] 还是List[String]时,编译器就会发出警告。事实上,编译器认为第二个匹配List[String] 的case子句是不可达代码,意味着第一个匹配List[Double] 的 case 子句可以匹配任意List。输出显示,对于两个输入,都打印出了 seq double。
    一个不太美观但却有效的解决方法是:

    首先匹配集合,然后用一个嵌套的匹配语句去匹配集合中的第一个元素,从而决定其类型。这样的话,我们也就必须单独处理空序列:

    // src/main/scala/progscala2/patternmatching/match-types2.sc 
    def doSeqMatch[T](seq: Seq[T]): String = seq match { 
      case Nil => "Nothing" 
      case head +: _ => head match { 
      case _ : Double => "Double" 
      case _ : String => "String" 
      case _ => "Unmatched seq element" 
    } 
    } 
    
    for { x <- 
        Seq(List(5.5,5.6,5.7), List("a", "b"), Nil) } yield {   x match {     case seq: Seq[_] => (s"seq ${doSeqMatch(seq)}", seq)     case _ => ("unknown!", x)     } }

    以上脚本返回了期望的输出:
    Seq((seq Double,List(5.5, 5.6, 5.7)), (seq String,List(a,b)), (seq Nothing,List()))。

  • 相关阅读:
    jq绑定on事件无效
    数字以0补全
    redis常用操作
    mysql数据操作日常
    centos端口映射
    centos7防火墙操作
    mysql5.7order by问题
    centos无法上网解决方法
    面试题
    ztree 获取子节点所有父节点的name的拼接
  • 原文地址:https://www.cnblogs.com/linbo3168/p/16544729.html
Copyright © 2020-2023  润新知