为什么在scala中使用concat运算符?

时间:2016-03-20 17:59:15

标签: scala functional-programming operators

在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。我错了吗?

2 个答案:

答案 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中是不可变的,因此附加到列表的末尾非常昂贵;将值预先添加到列表的开头是非常便宜的。