为什么必须为Scala中for循环中的模式匹配定义过滤器?
要创建一个可以在Scala中用于理解的新类,似乎你所要做的就是定义一个map函数:
scala> class C[T](items: T*) { | def map[U](f: (T) => U) = this.items.map(f) | } defined class C scala> for (x <- new C(1 -> 2,3 -> 4)) yield x res0: Seq[(Int,Int)] = ArrayBuffer((1,2),(3,4)) 但是,这仅适用于< - 的左侧没有模式匹配的简单循环。如果您尝试在那里进行模式匹配,您会得到一个投诉:过滤器方法未定义: scala> for ((k,v) <- new C(1 -> 2,3 -> 4)) yield k -> v <console>:7: error: value filter is not a member of C[(Int,Int)] for ((k,3 -> 4)) yield k -> v 为什么要在这里实现模式匹配所需的过滤器?我会认为Scala只会将上述循环转换为等效的地图调用: scala> new C(1 -> 2,3 -> 4).map{case (k,v) => k -> v} res2: Seq[(Int,4)) 但是这似乎工作正常,所以for循环必须被翻译成别的东西。什么是翻译成需要过滤方法? 解决方法
简短的答案:根据Scala规范,您不需要为您给出的示例定义“过滤器”方法,但是有一个
open bug表示当前需要。
漫长的答案:the Scala language specification中描述了应用于理解的绝对算法。我们从6.19节“For Comprehensions and For Loops”开始(我在查看规范的2.9版本):
你的问题的重点是,理解中的模式是否是给定表达式的“无可辩驳的”。 (该模式是’< - '之前的位,表达式是稍后的)。如果它是“无可辩驳的”,则不会添加withFilter,否则将需要它。 好,但是“无可辩驳”是什么意思?跳到第8.1.14节的规范(“无可辩驳的模式”)。大致来说,如果编译器可以证明匹配表达式时模式不能失败,那么模式是无可辩驳的,并且不会添加withFilter调用。 现在,您可以预期的示例是第8.1.14节中的第一种类型的无可辩驳的模式,即可变模式。所以第一个例子很容易让编译器确定不需要使用Filter。 你的第二个例子是潜在的第三种类型的无可辩驳的模式,一种构造函数模式。尝试将Tuple2 [Any,Any]与Tuple2 [Int,Int](参见规范中的8.1.6和8.1.7)匹配(k,v))成功,因为Int对于Any是无可辩驳的。因此,第二种模式也是无可辩驳的,不(不应该)需要一个withFilter方法。 在丹尼尔的例子中,Tuple2 [Any,Any]对于Any来说不是无可辩驳的,所以addFilter调用被添加。 顺便问一下,错误消息讲过滤方法,但是规范与Filter讨论 – 它已经用Scala 2.8改变了,参见this question and answer的gory细节。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |