2016-03-20 40 views
1

斯卡拉repl爲什麼在scala中向後使用concat運算符?

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。我假設有問題嗎?

+1

[?有什麼好處在斯卡拉右結合的方法(HTTP的可能重複:// stackoverflow.com/questions/1162924/what-good-are-right-associative-methods-in-scala) –

回答

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實現的,它包含一個頭是集合中的第一個元素,還有一個是尾部的剩餘元素的列表。這就是爲什麼添加元素比添加元素便宜得多,因爲它需要O(n)遍歷內部列表才能複製元素,並附加新值。

雖然價格不菲,仍然可以做到這一點使用:+運營商,這是左結合

scala> List(1,2,3) :+ 4 
res3: List[Int] = List(1, 2, 3, 4) 
2

:結尾的Scala運算符是右關聯的。因此,在您的示例中,您試圖將::運算符應用於Int

此外,List結構在Scala中是不可變的,因此追加到列表的末尾非常昂貴;將一個值預先添加到列表的開始處非常便宜。

相關問題