gpt4 book ai didi

scala - IndexedSeq [Int]与Array [Int]

转载 作者:行者123 更新时间:2023-12-03 15:23:56 25 4
gpt4 key购买 nike

来自Java背景,我正在学习Scala,以下内容使我感到非常困惑。为什么在这两个(非常相似但又不同)的构造中返回的类型不同,这些构造仅在构建源集合的方式上有所不同-

  val seq1: IndexedSeq[Int] = for (i <- 1 to 10) yield i


  val seq2: Array[Int] = for (i <- Array(1, 2, 3)) yield i

请为我指出正确的文献,以便在这里我能理解核心基础知识。

最佳答案

通常,有两种不同样式的收集操作库:

  • 类型保留:这就是您在问题
  • 中所困惑的地方
  • 泛型(不是“参数多态性”的意思,而是单词的标准英语意义)或“homogeneous”的

  • 保留类型的收集操作会尝试为 filtertakedrop等操作完全保留类型,这些操作只会使现有元素保持不变。对于 map之类的操作,它将尝试查找仍可以保存结果的最接近的父类(super class)型。例如。通过从 IntSetInt的功能在 String上进行映射显然不会导致 IntSet,而只会导致 Set。将 IntSet映射到 Boolean可以用 BitSet表示,但是我知道没有足够聪明的集合框架可以真正做到这一点。

    通用/同类收集操作始终返回相同的类型。通常,选择这种类型是非常通用的,以适应最广泛的用例。例如,在.NET中,集合操作返回 IEnumerable ,在Java中,它们返回 Stream ,在C++中,它们返回迭代器,在Ruby中,它们返回数组。

    直到最近,才有可能通过复制所有类型的所有操作来实现类型保留的收集操作。例如,Smalltalk集合框架是类型保留的,它通过让每个单个集合类重新实现每个单个集合操作来做到这一点。这导致大量重复的代码,并且是维护的噩梦。 (巧合的是,发明了许多新的面向对象的抽象方法,并就其如何应用于Smalltalk集合框架撰写了第一篇论文。有关示例,请参见 Traits: Composable Units of Behaviour。)

    据我所知, the Scala 2.8 re-design of the collections framework( see also this answer on SO)是第一次有人设法创建保留类型的集合操作,同时最大限度地减少(但不消除)重复。但是, the Scala 2.8 collections framework was widely criticized过于复杂,在过去的十年中需要不断的工作。实际上,它实际上也导致对Scala文档系统的完整重新设计,只是能够 hide the very complex type signatures that the type-preserving operations require。但是, this still wasn't enough,所以集合框架是 completely thrown out and re-designed yet again in Scala 2.13。 (此重新设计花了几年时间。)

    因此,对您的问题的简单答案是:Scala尝试尽可能多地保留集合的类型。

    在第二种情况下,集合的类型为 Array,当您在 map上使用 Array时,您将获得一个 Array

    在第一种情况下,集合的类型为 Range。现在,虽然 Range实际上没有元素。它只有一个起点,一个终点和一个步骤,并且在您迭代时按需生成元素。因此,使用新元素生成新的 Range并非易事。 map函数基本上需要能够对映射函数进行“反向工程”,以弄清楚新的起点和终点以及步骤应该是什么。 (这相当于解决停止问题,换句话说,这是不可能的。)如果执行以下操作,该怎么办:

    val seq1: IndexedSeq[Int] = for (i <- 1 to 10) yield scala.util.Random.nextInt(i)

    这里甚至没有明确定义的步骤,因此实际上不可能构建执行此操作的 Range

    因此,显然,映射到 Range不能返回 Range。因此,它做的第二件事是:它返回可以包含映射值的最精确的 Range super 类型。在这种情况下,恰好是 IndexedSeq

    在保留类型的收集操作方面,我们遇到了麻烦,我们认为这是某些操作契约(Contract)的一部分。例如,大多数人认为 map下集合的基数应该是不变的,换句话说, map应该将每个元素精确地映射到一个新元素,因此 map绝不应该改变集合的大小。但是,这段代码呢:

    Set(1, 2, 3).map { _ % 2 == 0 }
    //=> Set(true, false)

    在这里,您从 map取回了元素较少的集合,该集合仅应转换元素,而不能删除它们。但是,由于我们决定要保留类型的集合,并且 Set不能有重复的值,所以两个 false值实际上是相同的值,因此集合中只有一个。

    [可以争论的是,这实际上仅表明 Set不是集合,不应将其视为集合。 Set是谓词(“此元素是成员吗?”),而不是集合(“给我所有元素!”)

    关于scala - IndexedSeq [Int]与Array [Int],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61976188/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com