是否可以在 Scala for expression 中对类型进行模式匹配?
Is it possible to pattern match on type in a Scala for expression?
我正在尝试使用 for 表达式映射选项,但我只想匹配选项的内容是否属于特定类型。我认为可行的是:
for {
vcs: Mercurial <- maybeVcs
} yield vcs
但这会产生以下编译错误:
<console>:76: error: type mismatch;
found : sbtrelease.Mercurial => sbtrelease.Mercurial
required: sbtrelease.Vcs => ?
vcs: Mercurial <- get (releaseVcs in Compile)
^
是否可以对 for 表达式中的类型进行模式匹配?
你可以使用丑陋的测试:
for {
vcs <- maybeVcs
if vcs.instanceof[Mercurial]
} yield vcs
如果使用 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
这个模式匹配不起作用的事实实际上是一个错误(至少它不符合规范)。参见 https://issues.scala-lang.org/browse/SI-900。
但是,有一个简单的解决方法。
在某处定义以下对象:
object Id { unapply[T](x:T) = Some(x) }
现在您可以使用 Id(x)
作为匹配所有内容的模式匹配,并将 x
绑定到它匹配的任何内容。所以基本上是一个毫无意义的构造,因为 Id(pattern)
与 pattern
.
相同
但是,它有一个作用:Id(...)
中的类型注释不会被解释为类型注释,而是类型模式。因此
for {
Id(vcs: Mercurial) <- maybeVcs
} yield vcs
会有你想要的效果。 (与 不同的是,整个表达式的类型为 Seq[Mercurial]
而不是 Seq[Vcs]
。)
我正在尝试使用 for 表达式映射选项,但我只想匹配选项的内容是否属于特定类型。我认为可行的是:
for {
vcs: Mercurial <- maybeVcs
} yield vcs
但这会产生以下编译错误:
<console>:76: error: type mismatch;
found : sbtrelease.Mercurial => sbtrelease.Mercurial
required: sbtrelease.Vcs => ?
vcs: Mercurial <- get (releaseVcs in Compile)
^
是否可以对 for 表达式中的类型进行模式匹配?
你可以使用丑陋的测试:
for {
vcs <- maybeVcs
if vcs.instanceof[Mercurial]
} yield vcs
如果使用 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
这个模式匹配不起作用的事实实际上是一个错误(至少它不符合规范)。参见 https://issues.scala-lang.org/browse/SI-900。
但是,有一个简单的解决方法。 在某处定义以下对象:
object Id { unapply[T](x:T) = Some(x) }
现在您可以使用 Id(x)
作为匹配所有内容的模式匹配,并将 x
绑定到它匹配的任何内容。所以基本上是一个毫无意义的构造,因为 Id(pattern)
与 pattern
.
但是,它有一个作用:Id(...)
中的类型注释不会被解释为类型注释,而是类型模式。因此
for {
Id(vcs: Mercurial) <- maybeVcs
} yield vcs
会有你想要的效果。 (与 Seq[Mercurial]
而不是 Seq[Vcs]
。)