scala> val w = new ::[Int](4,Nil)
w: scala.collection.immutable.::[Int] = List(4)
scala> val x = List[Int](4)
x: List[Int] = List(4)
这两个表达式有什么区别? ::[Int](4)
是 List[int]
的实例吗,因为 ::[Int](4)
和 List[Int](4)
产量List(4)
?
最佳答案
::[T]
是代数数据类型的构造函数之一 List[T]
。另一个是Nil
。考虑以下inductive definition 列表
sealed trait List[+T]
case object Nil extends List[Nothing]
case class ::[T](head: T, tail: List[T]) extends List[T]
::
可能看起来有点奇怪,因为它纯粹是符号名称,在其他语言中有时被称为 Cons
。构造函数是创建 List[T]
类型的值的方法,这里有一些
Nil
::(1, Nil)
::(2, ::(1, Nil))
::(42, ::(2, ::(1, Nil)))
这些值具有归纳性质,具有一个显着的特性,即每当我们拥有一个值时,我们总是知道如何构造以下值。换句话说,归纳值意味着归纳值。例如,两者
::(2, ::(1, Nil))
和
::(51, ::(1, Nil))
通过构造函数 ::[Int]
的力量实现 ::(1, Nil)
的含义。
Is
::[Int]
the same asList[Int]
?
因为 Scala 使用 form of inheritance 实现代数数据类型,确实存在is-a-subtype-of关系
implicitly[::[Int] <:< List[Int]] // ok!
虽然不存在等于关系
implicitly[::[Int] =:= List[Int]] // error!
但是,在我看来,这些子类型关系不是代数数据类型的重点,在 Scala 中是偶然的。相反,构造函数 ::[T]
和正在构造其值的类型 List[T]
之间的关系更类似于函数<之间的关系/em> 和一个类型。
Is
new ::[Int](4, Nil)
the same asList[Int](4)
?
它们都计算出相同的值,例如以下遍
assert(new ::[Int](4, Nil) == List[Int](4))
但是我们得出这个值的方式却截然不同。在前一种情况下,我们直接使用 List[Int]
ADT 的构造函数,而在后一种情况下,我们实际上是在 companion 上调用 apply
方法 trait List[T]
List.apply[Int](4)
其中 apply
定义为
def apply[A](xs: A*): List[A] = xs.toList
现在在实践中我们很少需要考虑这些事情。通常我们只是简单地写一些像
List(4, 2, 42)
然后就完成了。 “低级”构造函数::
有时会在模式匹配期间显露出来,这是一种解构ADT的方式,例如,这里是递归获取列表中元素总和的实现
def sum(l: List[Int]): Int = {
l match {
case Nil => 0
case head :: tail => head + sum(tail)
}
}
sum(List(1, 2, 42))
// res1: Int = 45
关于list -::[Int] 与 List[Int] 相同吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59792287/