Scala 的 for-comprehension `if` 语句 [英] Scala's for-comprehension `if` statements
问题描述
scala 是否有可能在 for comprehension 中专门处理 if
中的条件?我在思考:
Is it possible in scala to specialize on the conditions inside an if
within a for comprehension? I'm thinking along the lines of:
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
要点是,通过产生 i
,我得到了一个可能不同类型的新集合(因此我将其称为专业化")-而不是过滤后的版本相同的 GenericCollection 类型.
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.
我问的原因是我看到了一些我无法弄清楚的东西(可以找到一个例子在这个 ScalaQuery 示例的第 33 行.它所做的是为数据库创建一个查询(即 SELECT ... FROM ... WHERE ...
),我原以为它会遍历上述查询的结果.
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.
推荐答案
所以,我想您是在问是否可以在 for-comprehension 中使用 if
语句来更改结果类型.答案是是的,但是……".
So, I think you are asking if it is possible for the if
statement in a for-comprehension to change the result type. The answer is "yes, but...".
首先,了解 for-comprehensions 是如何扩展的.Stack Overflow 上有一些问题在讨论它,您可以将参数传递给编译器,以便它向您展示发生了什么.
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.
无论如何,这段代码:
val evenColl = for { i <- collection if(Even) } yield i
翻译为:
val evenColl = collection.withFilter(i => Even).map(i => i)
所以,如果 withFilter
方法改变了集合类型,它会做你想做的——在这个简单的例子中.在更复杂的情况下,单独这样做是行不通的:
So, if the withFilter
method changes the collection type, it will do what you want -- in this simple case. On more complex cases, that alone won't work:
for {
x <- xs
y <- ys
if cond
} yield (x, y)
翻译为
xs.flatMap(ys.withFilter(y => cond).map(y => (x, y)))
在这种情况下,flatMap
决定返回什么类型.如果它从返回的结果中得到提示,那么它就可以工作.
In which case flatMap
is deciding what type will be returned. If it takes the cue from what result was returned, then it can work.
现在,在 Scala 集合上,withFilter 不会改变集合的类型.不过,您可以编写自己的类来实现这一点.
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 的 for-comprehension `if` 语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!