在scala中repl
scala> List(1) :: 2
<console>:8: error: value :: is not a member of Int
List(1) :: 2
但是
scala> 2 :: List(1);
res4: List[Int] = List(2, 1)
这是违反直觉的,因为如果从左到右读取中缀运算符,则上述行可以转换为
List(1) :: 2
List(1).::(2)
和
2 :: List(1)
2.::(List(1))
我认为Int
在::
的情况下没有方法List
。我错了吗?
答案 0 :(得分:3)
这是违反直觉的,因为如果向左读取中缀运算符 右
如果你从逻辑上考虑它,那就更有意义了。 ::
(cons)运算符将值预先添加到列表的开头,它不会将追加到列表的末尾。当你这样思考时,::
运算符是正确关联的事实是有道理的,因为它将一个元素粘贴到List
的开头:
scala> 4 :: List(3,2,1)
res1: List[Int] = List(4, 3, 2, 1)
内部实施相当简单:
def ::[B >: A] (x: B): List[B] =
new scala.collection.immutable.::(x, this)
List
在内部实现为LinkedList,其中包含作为集合中第一个元素的head,以及作为尾部的其余元素的列表。这就是为什么预先添加元素要比附加元素便宜得多,因为它需要对内部列表进行O(n)遍历才能复制元素,并附加新值。
虽然价格昂贵,但您仍然可以使用{em>左关联的:+
运算符来执行此操作:
scala> List(1,2,3) :+ 4
res3: List[Int] = List(1, 2, 3, 4)
答案 1 :(得分:2)
以:
结尾的Scala运算符是右关联的。因此,在您的示例中,您尝试将::
运算符应用于Int
。
此外,List
结构在Scala中是不可变的,因此附加到列表的末尾非常昂贵;将值预先添加到列表的开头是非常便宜的。