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

scala – 为什么要设置一个函数?

发布时间:2020-12-16 09:24:03 所属栏目:安全 来源:网络整理
导读:在Scala a Set中是一种功能: trait Set[A] extends (A = Boolean) 这使得不可能具有协变不变的集合,因为类型A以违反位置发生.相反,Seq不被定义为一个功能.现在已经有一些关于Set和Seqs这样设计的问题的内容: Why is Scala’s immutable Set not covariant
在Scala a Set中是一种功能:

trait Set[A] extends (A => Boolean)

这使得不可能具有协变不变的集合,因为类型A以违反位置发生.相反,Seq不被定义为一个功能.现在已经有一些关于Set和Seqs这样设计的问题的内容:

> Why is Scala’s immutable Set not covariant in its type?
> Scala: Why does Seq.contains take an Any argument,instead of an argument of the sequence type?
> Why does Seq.contains accept type Any rather than the type parameter A?

一个答案说,原因是数学背景.但这个答案没有多解释.那么,定义集合作为一个函数的具体优点是什么?如果不同的实现方式有什么不利之处呢?

解决方法

Set [A]类型的集合必须有一种方法来测试A类元素是否在集合中.该方法(应用)必须具有表示该元素的类型A的参数,并且该参数处于相反的位置.这意味着集合在其类型参数A中不能是协变的.所以 – 不是扩展函数接口,使得不可能具有协变不变集,它是存在逆变应用方法.

为了方便起见,扩展Function1界面可以传递集合并将其视为函数是有意义的.

相比之下,序列抽象没有一种方法来测试元素是否在序列中,它只具有索引方法 – apply采用整数索引,并返回该索引处的元素.序列也定义为函数,但类型为Int => A(其在A中是协变的),而不是A =>布尔值,作为集合.

如果您想了解更多关于类型安全性如何在类型参数A中被定义为协方差的情况,请参见此示例,其中集合实现对私有成员进行一些写入,以缓存查找(在@uV下面禁止方差检查和expensiveLookup的注释意味着模拟一个调用计算昂贵的检查,如果元素在集合中):

import annotation.unchecked.{uncheckedVariance => uV}

trait Set[+A] {
  def apply(elem: A @uV): Boolean
}

class CachingSet[+A >: Null] extends Set[A] {
  private var lastLookup: (A @uV,Boolean) = (null,false)
  private def expensiveLookup(elem: A @uV) = (elem,true)
  def apply(elem: A @uV): Boolean = {
    if (elem != lastLookup._1) lastLookup = expensiveLookup(elem)
    lastLookup._2
  }
  def lastQueriedElement: A = lastLookup._1
}

object Main extends App {
  val css = new CachingSet[String]
  val csa: CachingSet[AnyRef] = css

  csa.apply(new AnyRef)
  val s: String = css.lastQueriedElement // you'll get a ClassCastException here
}

(编辑:李大同)

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

    推荐文章
      热点阅读