为什么在这种情况下需要过滤器实现?

时间:2013-04-16 12:51:04

标签: scala filter foreach pattern-matching

以下代码无法编译:

scala> case class T3( x:Int,y:Int,z:Int) { def foreach[U](f:((Int,Int,Int)) => U) = f( (x,y,z) ) }
defined class T3

scala> for ( (x,y,z) <- T3(1,2,3) ) { println (x,y,z) }
<console>:10: error: value filter is not a member of T3
              for ( (x,y,z) <- T3(1,2,3) ) { println (x,y,z) }
                                 ^

我不明白为什么这段代码需要过滤器,因为它始终匹配?

修改 对于我的问题,添加一个无意义的过滤器实现就足够了:

scala> case class T3( x:Int,y:Int,z:Int) { def foreach[U](f:((Int,Int,Int)) => U) = f( (x,y,z) )
     | def filter(p: ((Int,Int,Int)) => Boolean) = this }
defined class T3

scala> for ( (x,y,z) <- T3(1,2,3) ) { println (x,y,z) }
(1,2,3)

scala> 

2 个答案:

答案 0 :(得分:2)

根据Scala language specification,生成器p <- e被转换为withFilter调用,除非该模式是“无可辩驳的”。给出了一个无可辩驳的模式的三个条件:

  1. p是一种变量模式。
  2. 显然,事实并非如此。

    1. p是一种打字模式x : T''T <: T',其中e : T
    2. 同样,事实并非如此。

      1. p是构造函数模式c(p1,...,pn),类型T是类c的实例,类型为T的主构造函数(第5.3节)参数类型T1, ..., Tnpi每个Ti都无法参与。
      2. 这里的问题是虽然(x,y,z)Tuple3的构造函数模式,但类型T(此处T3)不是{{Tuple3的实例1}} - 只有foreach方法的返回类型。转换非无可辩驳的模式是消除for表达式的第一步,因此在考虑返回类型foreach之前。

        因此,模式无法显示为无可辩驳。

        编辑:虽然根据规范上述内容似乎有道理,但我看不出实际上有什么意义!例如,我的解释表明以下模式应该是无可辩驳的:

        (a,b) <- (1,2)
        

        尽管它没有任何意义!它显然正在寻找一些东西来确定结果类型以检查无法反驳,似乎有些东西是withFilter方法。这表明它需要withFilter方法才能确定是否需要withFilter方法......

        似乎存在各种各样的错误:例如https://github.com/scala/scala/pull/1893。我猜这也许是另一个破案。

答案 1 :(得分:0)

这将有效:

 for ( T3(x,y,z) <- List(T3(1,2,3)) ) { println (x,y,z) }

也是这样:

 for ( T3(x,y,z) <- Some(T3(1,2,3)) ) { println (x,y,z) }

for理解似乎需要盒装值。