Reputation: 41939
Given:
$cat build.sbt
scalaVersion := "2.11.8"
libraryDependencies += "org.scala-lang.modules" %% "scala-xml" % "1.0.6"
and, then
$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
Evidently, Seq#unapply
is not being used:
scala> exactlyOne( Seq(1) )
res2: Option[Int] = Some(1)
My understanding is that unapply
will get called, typically on the class's companion object
.
I found 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])]), but I'm not sure if that's being called.
Which method is getting called on match
here?
Upvotes: 0
Views: 410
Reputation: 55569
A NodeSeq
is not a List
, so trying to pattern match it as one will fail. If you wanted to match it using unapplySeq
of some kind, you would need to do it in this way:
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
Upvotes: 3