斯卡拉的理解`if`陈述

时间:2011-10-31 03:36:21

标签: scala

scala是否有可能专注于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

要点是,通过屈服i,我得到一个可能不同类型的新集合(因此我将其称为“专业化”) - 而不是仅仅是相同GenericCollection的过滤版本类型。

我问的原因是我看到了一些我无法弄清楚的东西(可以找到一个例子on line 33 of this ScalaQuery example。它的作用是为数据库创建一个查询(即SELECT ... FROM ... WHERE ...),我希望它可以迭代所述查询的结果。

2 个答案:

答案 0 :(得分:48)

所以,我认为您在询问for-comprehension中的if语句是否有可能更改结果类型。答案是“是的,但是......”。

首先,了解如何扩展理解。这里有关于Stack Overflow讨论它的问题,有些参数可以传递给编译器,因此它会告诉你发生了什么。

无论如何,这段代码:

val evenColl = for { i <- collection if(Even) } yield i

翻译为:

val evenColl = collection.withFilter(i => Even).map(i => i)

因此,如果withFilter方法更改了集合类型,它将执行您想要的操作 - 在这种简单的情况下。在更复杂的案例中,仅此一点不起作用:

for {
  x <- xs
  y <- ys
  if cond
} yield (x, y)

翻译为

xs.flatMap(ys.withFilter(y => cond).map(y => (x, y)))

在这种情况下flatMap决定返回什么类型。如果它从返回的结果中获取提示,那么它可以工作。

现在,在Scala Collections上, withFilter不会更改集合的类型。但是,您可以编写自己的类来执行此操作。

答案 1 :(得分:5)

是的,你可以 - 请参考this tutorial以获得一个简单的例子。您引用的scala查询示例也在对集合进行迭代,然后使用该数据构建查询。