【问题标题】:Why is a filter implementation needed in this case?为什么在这种情况下需要过滤器实现?
【发布时间】:2013-04-08 21:18:38
【问题描述】:

以下代码编译失败:

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> 

【问题讨论】:

  • this 的可能重复项

标签: scala filter foreach pattern-matching


【解决方案1】:

这将起作用:

 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 理解需要装箱的值。

【讨论】:

  • 问题是初始示例中的元组 T3 装箱。
  • 我希望 for ( T3(x,y,z) &lt;- T3(1,2,3) ) { println (x,y,z) } 也能工作,但没有。 for((x,y,z) &lt;- Tuple3(1,2,3))yield x 也失败了。我会尝试阅读更多内容并回复您。
【解决方案2】:

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

  1. p 是一个可变模式。

显然,情况并非如此。

  1. p 是一个类型化的模式x : T''T &lt;: T',其中e : T

同样,显然不是这样。

  1. p 是构造函数模式c(p1,...,pn)T 类型是类c 的实例,T 类型的主构造函数(§5.3)具有参数类型T1, ..., Tn,每个piTi 无可辩驳。

这里的问题是,虽然(x,y,z)Tuple3 的构造函数模式,但T 类型(这里是T3)不是Tuple3 的实例——只有foreach 方法是。无可辩驳的模式转换是对for 表达式进行脱糖的第一步,因此在考虑返回类型为foreach 之前。

因此,这种模式不能被证明是无可辩驳的。

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

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

尽管这毫无意义!它显然在寻找一些东西来确定结果类型以检查不可辩驳性,并且似乎是withFilter 方法。这表明它需要一个withFilter 方法来确定是否需要withFilter 方法...

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

【讨论】:

  • 当你说(a,b) &lt;- (1,2) 不应该是无可辩驳的时候,我很困惑……你能详细说明一下吗?
  • (a,b) = (1,2) 应该没问题,但显然它不是 p &lt;- e 中的 e 的类型,应该检查 p 的无可辩驳性 - 它是容器“内部”元素的类型.
  • p = (a,b) 符合SLS 中的第三种无可辩驳的情况? (a,b) 等价于Tuple2(a,b) 并且Tuple2 是一个case 类,所以我们有提取的构造函数类型T 对应于Tuple2。那么参数的模式ab 应该是无可辩驳的,因为它们是可变模式。我错了吗?
  • 关键是 SLS 声明,对于模式 p &lt;-ep 应针对 e 的类型检查不可辩驳性 - 但 e 的类型是容器类型,而不是包含的类型。我在 SLS 中找不到它指定哪个类型 e 模式实际上是针对不可辩驳性检查的,但实验表明它是从 withFilter 的类型派生的。
  • 好的,现在我明白了,我错过了 SLS 所说的“对于 e 的类型而言并非无可辩驳”。我同意这没有多大意义。谢谢
猜你喜欢
  • 2016-08-08
  • 2016-07-17
  • 1970-01-01
  • 2013-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-15
  • 1970-01-01
相关资源
最近更新 更多