为什么scala模式匹配在for循环中不适用于类型匹配?

时间:2012-07-09 11:20:20

标签: scala casting pattern-matching

我正在对API进行编码,这使我可以访问远程文件系统。 API返回文件和目录列表作为节点对象列表(父文件和目录)。

我想只在目录上工作,忽略文件。我尝试在for循环中使用类型模式匹配,但它不起作用:

for {
    dir: CSDir <- workarea.getChildren() // <-- I'm getting an error here complaining about type conversion
} {
    println(dir)
}

以下是使用scala基本对象运行它而没有依赖关系的类似示例:

val listOfBaseObjects:List[Any] = List[Any]("a string", 1:Integer);

for (x: String <- listOfObjects) {
  println(x)
}

我最终在for循环的一侧使用常规模式匹配,并且工作正常:

// This works fien
for (child <- workarea.getChildren()) {
  child match {
    case dir: CSDir => println(dir)
    case _ => println("do not nothing")
  }
}

问题:

你能告诉我为什么第一个/第二个例子在scala 1.9中不起作用吗?

在&#34; Scala编程&#34;广告for循环使用与match相同的模式匹配,因此它应该有用。

如果for和match不同,那么如果你能指出一些有更多细节的文章会很棒。分配中的模式匹配怎么样?

更新

我无法接受一个答案,该答案表明跳过for循环中的元素是不可能的,因为这与&#34; Prog相矛盾。在斯卡拉&#34;。这是第23.1节中的一个片段:

  

pat <- expr ...模式pat与该列表的所有元素逐一匹配。 ...如果匹配失败,则不会抛出MatchError。相反,该元素只是从迭代中丢弃

确实以下示例工作得很好:

scala> val list = List( (1,2), 1, 3, (3,4))
scala> for ((x,y) <- list) { println (x +","+ y) }
1,2
3,4

为什么类型匹配不起作用?

3 个答案:

答案 0 :(得分:12)

这是long-standing issue 900,之前已多次讨论过。常见的解决方法是使用以下内容:

for (y@(_y:String) <- listOfBaseObjects) {
    println(y)
}

Jason Zaugg在对上述票证的评论中提供了一个更好的版本:

object Typed { def unapply[A](a: A) = Some(a) }

for (Typed(y : String) <- listOfBaseObjects) {
    println(y)
}

答案 1 :(得分:1)

您要做的主要是:迭代workarea.getChildren()类型CSDir的所有元素(换句话说:匹配某些条件)。 普通循环/用于理解迭代所有元素。你不能说:迭代所有具有这种类型的元素并跳过其他元素。你必须更明确。

您如何看待:

workarea.getChildren() collect {case dir: CSDir => dir} foreach println

它完全符合您的要求:收集 workarea.getChildren()的所有元素,为每个调用println

答案 2 :(得分:0)

这个怎么样:

val listOfBaseObjects: List[Any] = List[Any]("a string", 1:Integer);

for (x <- listOfBaseObjects if x.isInstanceOf[String]) {
  println(x)
}