Scala 的 for-comprehension `if` 语句
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7949785/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Scala's for-comprehension `if` statements
提问by Dylan
Is it possible in scala to specialize on the conditions inside an ifwithin a for comprehension? I'm thinking along the lines of:
在Scala中是否有可能专门研究in内的条件if以进行理解?我正在考虑以下方面:
val collection: SomeGenericCollection[Int] = ...
trait CollectionFilter
case object Even extends CollectionFilter
case object Odd extends CollectionFilter
val evenColl = for { i <- collection if(Even) } yield i
//evenColl would be a SomeGenericEvenCollection instance
val oddColl = for { i <- collection if(Odd) } yield i
//oddColl would be a SomeGenericOddCollection instance
The gist is that by yielding i, I get a new collection of a potentially different type (hence me referring to it as "specialization")- as opposed to just a filtered-down version of the same GenericCollection type.
要点是,通过 yielding i,我得到了一个可能不同类型的新集合(因此我将其称为“专业化”)——而不仅仅是相同 GenericCollection 类型的过滤版本。
The reason I ask is that I saw something that I couldn't figure out (an example can be found on line 33 of this ScalaQuery example. What it does is create a query for a database (i.e. SELECT ... FROM ... WHERE ...), where I would have expected it to iterate over the results of said query.
我问的原因是我看到了一些我无法弄清楚的东西(可以在这个 ScalaQuery 示例的第 33 行找到一个示例。它所做的是为数据库(即SELECT ... FROM ... WHERE ...)创建一个查询,这是我所期望的迭代所述查询的结果。
回答by Daniel C. Sobral
So, I think you are asking if it is possible for the ifstatement in a for-comprehension to change the result type. The answer is "yes, but...".
所以,我认为您是在问iffor-comprehension 中的语句是否可以更改结果类型。答案是“是的,但是……”。
First, understand how for-comprehensions are expanded. There are questions here on Stack Overflow discussing it, and there are parameters you can pass to the compiler so it will show you what's going on.
首先,了解 for-comprehensions 是如何扩展的。Stack Overflow 上有一些问题在讨论它,您可以将参数传递给编译器,以便它向您展示正在发生的事情。
Anyway, this code:
无论如何,这段代码:
val evenColl = for { i <- collection if(Even) } yield i
Is translated as:
译为:
val evenColl = collection.withFilter(i => Even).map(i => i)
So, if the withFiltermethod changes the collection type, it will do what you want -- in this simple case. On more complex cases, that alone won't work:
因此,如果该withFilter方法更改了集合类型,它将执行您想要的操作——在这个简单的例子中。在更复杂的情况下,单独这样做是行不通的:
for {
x <- xs
y <- ys
if cond
} yield (x, y)
is translated as
被翻译为
xs.flatMap(ys.withFilter(y => cond).map(y => (x, y)))
In which case flatMapis deciding what type will be returned. If it takes the cue from what result was returned, then it can work.
在这种情况下flatMap决定返回什么类型。如果它从返回的结果中获取线索,那么它就可以工作。
Now, on Scala Collections, withFilter doesn't change the type of the collection. You could write your own classes that would do that, however.
现在,在 Scala 集合上,withFilter 不会改变集合的类型。但是,您可以编写自己的类来做到这一点。
回答by aishwarya
yes you can - please refer to this tutorialfor an easy example. The scala query example you cited is also iterating on the collection, it is then using that data to build the query.
是的,您可以 - 请参阅本教程以获取简单示例。您引用的 scala 查询示例也在迭代集合,然后使用该数据来构建查询。

