【问题标题】:Pattern Matching on scala.xml.NodeSeqscala.xml.NodeSeq 上的模式匹配
【发布时间】:2016-12-03 05:00:22
【问题描述】:

给定:

$cat build.sbt
scalaVersion := "2.11.8"

libraryDependencies += "org.scala-lang.modules" %% "scala-xml"   % "1.0.6"

然后

$sbt console

def exactlyOne[A](xs: Seq[A]): Option[A] = xs match {
 case head :: Nil => Some(head)
 case _           => None
}

scala> val xml = <root><a/></root>
xml: scala.xml.Elem = <root><a/></root>

scala> xml \ "a"
res3: scala.xml.NodeSeq = NodeSeq(<a/>)

scala> exactlyOne( res3 )
res4: Option[scala.xml.Node] = None

显然,Seq#unapply 没有被使用:

scala> exactlyOne( Seq(1) )
res2: Option[Int] = Some(1)

我的理解是unapply 会被调用,通常是在班级的companion object 上。

我找到了Node#unapplySeq (http://www.scala-lang.org/api/2.11.8/scala-xml/index.html#scala.xml.Node$@unapplySeq(n:scala.xml.Node):Some[(String,scala.xml.MetaData,Seq[scala.xml.Node])]),但我'不确定这是否被调用。

match 这里调用了哪个方法?

【问题讨论】:

    标签: xml scala


    【解决方案1】:

    NodeSeq 不是List,因此尝试将其作为模式匹配将失败。如果你想使用某种unapplySeq 来匹配它,你需要这样做:

    def exactlyOne[A](xs: Seq[A]): Option[A] = xs match {
      case Seq(head) => Some(head)
      case _ => None
    }
    
    scala> exactlyOne(<root>hello</root>)
    res5: Option[scala.xml.Node] = Some(<root>hello</root>)
    
    scala> exactlyOne(<root>hello</root><foo>world</foo>)
    res6: Option[scala.xml.Node] = None
    

    【讨论】:

    • 那么,在调用match时,Seq#unapplySeq将如何解决-scala-lang.org/api/2.11.8/…
    • @KevinMeredith 我不确定我是否明白你在问什么。当编译器看到case Seq(...) 时,它会寻找Seq.unapplySeq.unapplySeq(并找到后者)。
    • 那么 unaply 和 unapplySeq 对于匹配是特殊的吗?换句话说,我们不能使用其他方法来匹配?
    • 参见scala-lang.org/files/archive/spec/2.11/… 和以下部分。是的,它们很特别。
    猜你喜欢
    • 2015-09-30
    • 1970-01-01
    • 1970-01-01
    • 2019-03-19
    • 2016-11-27
    • 2018-11-09
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多