[英]Is it possible to pattern match on type in a Scala for expression?
I'm trying to use a for expression to map over an Option, but I only want to match if the contents of the Option are of a specific type. 我正在尝试使用for表达式来映射Option,但我只想在Option的内容属于特定类型时进行匹配。 What I thought would work is this: 我认为可以的是这样的:
for {
vcs: Mercurial <- maybeVcs
} yield vcs
But that yields the following compile error: 但这会产生以下编译错误:
<console>:76: error: type mismatch;
found : sbtrelease.Mercurial => sbtrelease.Mercurial
required: sbtrelease.Vcs => ?
vcs: Mercurial <- get (releaseVcs in Compile)
^
Is it possible to pattern match on type in a for expression? 是否可以在for表达式的类型上进行模式匹配?
It's really straightforward if you use collect
instead of for
: 如果您使用collect
而不是for
这真的很简单:
trait A
case class B(x: Int) extends A
case class C(y: Int) extends A
val someB: Option[A] = Some(B(2))
val someC: Option[A] = Some(C(2))
val noneA: Option[A] = None
someB.collect { case n: B => n } // Some(B(2))
someC.collect { case n: B => n } // None
noneA.collect { case n: B => n } // None
The fact that this pattern match does not work is actually a bug (at least its not in accordance with the spec). 这种模式匹配不起作用的事实实际上是一个错误(至少与规范不符)。 See https://issues.scala-lang.org/browse/SI-900 . 参见https://issues.scala-lang.org/browse/SI-900 。
However, there is a simple workaround. 但是,有一个简单的解决方法。 Define somewhere the following object: 在某处定义以下对象:
object Id { unapply[T](x:T) = Some(x) }
Now you can use Id(x)
as a pattern match that matches everything, and just binds x
to whatever it matched. 现在,您可以将Id(x)
用作匹配所有内容的模式匹配项,并将x
绑定到任何匹配项。 So basically a pointless construct, since Id(pattern)
is the same as pattern
. 所以基本上没有意义的构造,因为Id(pattern)
与pattern
相同。
However, it has one effect: A type annotation inside Id(...)
will not be interpreted as a type annotation, but as a type pattern. 但是,它具有一种效果: Id(...)
内部的类型注释将不解释为类型注释,而是解释为类型模式。 Thus 从而
for {
Id(vcs: Mercurial) <- maybeVcs
} yield vcs
will have the effect you desire. 将达到您想要的效果。 (And differently from Bob's answer , the overall expression will have type Seq[Mercurial]
and not Seq[Vcs]
.) (与Bob的回答不同,整个表达式的类型将为Seq[Mercurial]
而不是Seq[Vcs]
。)
You can use an ugly test: 您可以使用一个丑陋的测试:
for {
vcs <- maybeVcs
if vcs.instanceof[Mercurial]
} yield vcs
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.