0

我想知道,为什么这段代码不能编译?

val files = (new java.io.File(".")).listFiles
for (file <- files if file.getName.endsWith(".scala")) {
  yield file
}
4

4 回答 4

10

简短的回答是,您的代码包含语法错误,因为yield关键字包含在提交给 for-comprehension 的代码块内。当编译器在您的for之后直接遇到花括号时,它会将其视为影响 for 理解的副作用,并且不理解您的意思yield

对于长答案,我们需要更多地了解理解。

For-comprehensions 有许多可能的表达方式,每个看似微小的差异都会极大地改变 for-comprehension 的行为。

我们来看看最简单的语法

for(generator1) { code_block }

请注意,generator1code_block是符号,而不是文字代码。生成器具有以下语法...

identifier <- expression

请注意,任何表达式都不起作用。对于上面的示例语法,表达式必须评估为定义foreach方法的某个对象,因为这种用于理解的语法表示code_block应该是副作用代码(即在某些外部范围内改变某些变量,或写入数据库, 或其他...),并且 for-comprehension 本身不应评估为一个值(事实上,如果您尝试将 for 表达式分配给一个变量,您将获得的值将是 Unit)。

在您的情况下,您打算编写的是以下稍微复杂的语法。

for(generator1 guard1) yield { code_block }

在此语法中,我们引入了一些新的语法元素,并且在幕后还引入了一些新要求。首先,让我们分解一下。

和以前一样,guard1确实是一个符号,实际语法实际上看起来更像...

if boolean_expression

当你有一个保护表达式时,这也意味着我们之前讨论的生成器1 的表达式也必须计算为定义过滤器方法的对象。请特别注意,我们还没有讨论特定的 trait/interface/abstract 类。Scala 的“for-comprehensions”利用了鸭子类型,因此任何实现了您使用的特定语法所需方法的对象都可以在 for-comprehension 构造中使用。这是非常强大的。

无论如何,回到我们的新语法,另一个关键区别是yield关键字。这个关键字对我们的生成器表达式施加了另一个限制,因为现在我们的生成器必须定义一个map方法。但是,这也解除了使用foreach方法的限制,因为在同一个 for-comprehension 中不能同时存在和不存在yield关键字。

使用yield关键字,现在期望code_block是无副作用的代码,而是某种形式的转换。此外,for-comprehension 现在计算为一个值(类似于用于生成器的表达式的输出类型)。这是因为,在幕后,for-comprehension 实际上只是调用map

这应该足以回答您的问题,但我强烈建议您阅读 map/flatmap/foreach 和 for-comprehensions,因为还有很多我没有在这里介绍的内容。

于 2013-09-05T05:43:00.707 回答
2

这在你看来如何?

if (flag) {
  // some code
} { else
  // other code
}

else看起来是在正确的地方吗?与 for-comprehensions 相同:yield必须位于第一个括号(或大括号)和产生的表达式之间。

于 2013-09-05T05:20:48.833 回答
1

这一定是圣经说的原因:

Avoid the temptation to write things like this:

  for (file <- filesHere if file.getName.endsWith(".scala")) {
    yield file  // Syntax error!
  }

章节和诗句,就在这个锚之前。

希望这会有所帮助:在for手段 foreach 之后的 expr;for 均值映射后的 yield expr。对于这种对 SO 的影响,肯定有答案。

于 2013-09-05T05:06:47.043 回答
1

输出大括号

scala> val r = for (file <- files if file.getName.endsWith(".scala")) yield file

r: Array[java.io.File] = Array()

如果你愿意,你可以在 yield 之后写大括号:yield {file}

于 2013-09-05T05:23:45.710 回答