加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

为什么必须为Scala中for循环中的模式匹配定义过滤器?

发布时间:2020-12-16 09:33:29 所属栏目:安全 来源:网络整理
导读:要创建一个可以在Scala中用于理解的新类,似乎你所要做的就是定义一个map函数: scala class C[T](items: T*) { | def map[U](f: (T) = U) = this.items.map(f) | }defined class Cscala for (x - new C(1 - 2,3 - 4)) yield xres0: Seq[(Int,Int)] = ArrayB
要创建一个可以在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版本):

In a first step,every generator p <- e,where p is not irrefutable (§8.1) for the type of e is replaced by p <- e.withFilter { case p => true; case _ => false }

你的问题的重点是,理解中的模式是否是给定表达式的“无可辩驳的”。 (该模式是’< - '之前的位,表达式是稍后的)。如果它是“无可辩驳的”,则不会添加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细节。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读