【问题标题】:Scala abstract value members on list returning unexpected result?列表上的Scala抽象值成员返回意外结果?
【发布时间】:2014-05-10 15:40:56
【问题描述】:

我不确定这是一个错误还是我对 Scala 的理解不够好。我今天在 REPL 中玩了一些列表功能。这是我所做的:

首先,我创建了一个列表:

scala> val myList = List(1.0, 2.0, 3.0)
myList: List[Double] = List(1.0, 2.0, 3.0)

接下来,我通过添加另一个双精度来创建另一个列表:

scala> val newMyList = 4.0 :: myList
newMyList: List[Double] = List(4.0, 1.0, 2.0, 3.0)

现在,当我在 newMyList 上询问 productArity (List.productArity) 时:

scala> print(newMyList.productArity)
2

它似乎仍然将第一个列表与另一个列表区别对待。这是预期的行为还是错误?

scala> print(newMyList.productElement(0))
4.0
scala> print(newMyList.productElement(1))
List(1.0, 2.0, 3.0)

注意,当我尝试访问高于 0、1 的元素时,我得到了 java.lang.IndexOutOfBoundsException。2 应该返回 2.0,3 应该返回 3.0,对吧?

【问题讨论】:

    标签: scala arity


    【解决方案1】:

    Scala 中的List 是一个基于 cons-cell 的结构,类似于 LISP 语言中使用的列表:它由单元组成,每个单元都有一个头元素和一个尾元素,最后一个单元格有一个尾元素Nil.

    Scala 中的空单元格是Nil,非空单元格是::(又名“缺点”)。这两种具体的列表子类型被实现为提供您所引用的 Product 特征的案例类。

    所以不是

    List(1.0, 2.0, 3.0)
    

    你可以想到

    ::(1.0, ::(2.0, ::(3.0, Nil)))
    

    或图形解释

    Cons(1.0, .)
              Cons(2.0, .)
                        Cons(3.0, .)
                                  Nil
    

    :: 是 arity 2 的乘积,第一个元素是头部,第二个元素是尾部。这就是为什么您将 4List(1, 2, 3) 作为两个产品元素添加到您的第二个列表中的原因。

    要访问列表中的元素,您可以改用apply。列表大小由size给出:

    List(4.0, 1.0, 2.0, 3.0).apply(2) // -> 2.0
    List(4.0, 1.0, 2.0, 3.0).size     // -> 4
    

    【讨论】:

      【解决方案2】:

      List - Nil:: 有两种可能的情况。

      :: 的定义类似于:

      case class ::[A](val head: A, val tail: List[A]) extends List[A]
      

      所以它是一个有两个元素的产品,列表的头部和尾部。

      这就是为什么 productArity 的非空列表返回 2,因为您正在调用 ::.productArity

      相比之下,Nil.productArity 返回 0。

      newMyList.productElement(0) 是列表的头部,因为您从 :: 获取第一个元素,而 newMyList.productElement(1) 是列表的尾部。 Cons 实例中没有更多元素,因此任何大于 1 的索引都超出范围。

      如果你想索引列表本身,你可以使用apply 方法:

      print(newMyList(2))
      

      【讨论】:

        猜你喜欢
        • 2021-09-02
        • 2023-02-05
        • 1970-01-01
        • 2017-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多