列表上的Scala抽象值成员返回意外结果?

Eri*_*yte 0 scala arity

我不确定这是一个bug还是我不太了解Scala.今天我在REPL中玩了一些列表功能.这是我做的:

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

scala> val myList = List(1.0, 2.0, 3.0)
myList: List[Double] = List(1.0, 2.0, 3.0)
Run Code Online (Sandbox Code Playgroud)

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

scala> val newMyList = 4.0 :: myList
newMyList: List[Double] = List(4.0, 1.0, 2.0, 3.0)
Run Code Online (Sandbox Code Playgroud)

现在,当我在newMyList上请求productArity(List.productArity)时:

scala> print(newMyList.productArity)
2
Run Code Online (Sandbox Code Playgroud)

它似乎仍然以不同于其他列表的方式处理第一个列表.这是一个预期的行为还是一个错误?

scala> print(newMyList.productElement(0))
4.0
scala> print(newMyList.productElement(1))
List(1.0, 2.0, 3.0)
Run Code Online (Sandbox Code Playgroud)

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

0__*_*0__ 5

ListScala中的A 是一种基于cons-cell的结构,类似于LISP语言中使用的列表:它由每个单元组成,每个单元都有一个head元素和一个tail元素,其中最后一个单元格的尾部元素为Nil.

Scala中的空单元格Nil是非空单元格::(又名"Cons").列表的这两个具体子类型实现为提供Product您引用的特征的案例类.

而不是

List(1.0, 2.0, 3.0)
Run Code Online (Sandbox Code Playgroud)

你可以想到

::(1.0, ::(2.0, ::(3.0, Nil)))
Run Code Online (Sandbox Code Playgroud)

或图解说明

Cons(1.0, .)
          Cons(2.0, .)
                    Cons(3.0, .)
                              Nil
Run Code Online (Sandbox Code Playgroud)

A ::是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
Run Code Online (Sandbox Code Playgroud)