8

我正在针对一个 API 进行编码,该 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 中不起作用吗?

在“Scala 编程”中, for循环被宣传为使用相同的模式匹配,match因此它应该可以工作。

如果 for 和 match 不同,如果您能指出一些更详细的文章,那就太好了。分配中的模式匹配怎么样?

更新:

我不能接受一个回答说不可能跳过 for 循环中的元素,因为这与“Prog. in scala”相矛盾。这是第 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

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

4

3 回答 3

12

这是长期存在的问题 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)
}
于 2012-07-09T13:05:50.463 回答
1

你想要做的基本上是:迭代所有workarea.getChildren()类型的元素CSDir(换句话说:匹配一些标准)。普通循环/for 理解迭代所有元素。你不能说:遍历所有具有这种类型的元素并跳过其他元素。你必须更明确。

你有什么想法:

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

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

于 2012-07-09T11:27:50.977 回答
-1

这个怎么样:

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

for (x <- listOfBaseObjects if x.isInstanceOf[String]) {
  println(x)
}
于 2015-06-19T18:50:20.433 回答