List 为什么在scala中创建列表时需要Nil?
清单上有一个基本问题 当我尝试使用cons运算符创建列表时,出现以下错误List 为什么在scala中创建列表时需要Nil?,list,scala,List,Scala,清单上有一个基本问题 当我尝试使用cons运算符创建列表时,出现以下错误 scala> val someList = 1::2 <console>:10: error: value :: is not a member of Int val someList = 1::2 ^ 我想知道为什么在我们创建一个列表时,至少需要一次Nil Nil是数据类型吗?还是空元素?正是因为这个原因 value::不是Int的成员 在Scala中,运算
scala> val someList = 1::2
<console>:10: error: value :: is not a member of Int
val someList = 1::2
^
我想知道为什么在我们创建一个列表时,至少需要一次Nil
Nil是数据类型吗?还是空元素?正是因为这个原因 value::不是Int的成员 在Scala中,运算符实际上是对象上的函数。在本例中,
:
是Nil
对象上的函数,该对象实际上是一个空列表对象
当您执行1::2
时,Scala会在2
上查找名为:
的函数,但找不到该函数。这就是它失败的原因
注意:在Scala中,如果运算符的最后一个字符不是冒号,则在第一个操作数上调用运算符。例如,
1+2
基本上是1.+(2)
。但是,如果最后一个字符是冒号,则在右侧操作数上调用运算符。所以在这种情况下,1::Nil
实际上是Nil::(1)
。由于::
返回另一个列表对象,您可以将其链接,就像1::2::Nil
实际上是,Nil:::(2)。:(1)
名称以:
结尾的中缀运算符被解释为右操作数上的方法调用。因此1::2
是2:::(1)
,即它调用2
上的方法:
。类似地,1::2::Nil
是Nil.:::(2)。:(1)
第一个方法不起作用的原因是
2
是Int
,而Int
s没有:
方法。第二种方法之所以有效,是因为Nil
是一个列表,而列表确实有一个:
方法。由于列表的结果。:
也是一个列表,您仍然可以对第一个:
的结果调用:
,Scala中以冒号结尾的任何运算符都定义在右操作数上。
因此,当您编写1::2
时,意味着:
应该在2
上定义,即在Int
上定义,但事实并非如此
Nil
是List
的一个值,上面定义了一个方法:
。因此,当您编写1::2::Nil
时,它被评估为(Nil::(1)
Nil
是创建列表作为递归数据结构的基本构建块。列表是一种有用的数据结构,它提供对头部(第一个元素)的恒定时间访问
列表在它的最小核心,是建立在3个操作之上的
头
,尾
,和空
Nil
是List
的单例子类,因此它是同类实例中的一个特殊实例,表示空列表。cons操作符:
在列表上定义,通过在列表中的一个元素前面加前缀,递归地构建一个列表
参见trait列表
和objectNil
的定义(高度简化)
由于任何以:
结尾的标识符/运算符都与右侧关联,:
运算符也与右侧关联
编写1::2::3
时,scala会尝试将此调用重写为3::(2::(1))
。i、 E3成为第一次调用:
的接收者,该调用在任何任意数据类型(本例中为Int)上都不存在
这就是为什么你总是在一个空的列表上建立一个空的列表-Nil。可以将其视为在空列表Nil
上一个接一个地为每个元素添加前缀
scala> val someList = 1::2::Nil
someList: List[Int] = List(1, 2)
scala> Nil
res0: scala.collection.immutable.Nil.type = List()
trait List[A] {
def head: A
def tail: List[A]
def isEmpty: Boolean
}
case object Nil extends List[Nothing] {
def head = throw new NoSuchElementException("head of empty list")
def tail = throw new UnsupportedOperationException("tail of empty list")
def isEmpty = true
}