스칼라에서 목록 :::
과 ++
연결 목록 간에 차이점이 있습니까?
scala> List(1,2,3) ++ List(4,5)
res0: List[Int] = List(1, 2, 3, 4, 5)
scala> List(1,2,3) ::: List(4,5)
res1: List[Int] = List(1, 2, 3, 4, 5)
scala> res0 == res1
res2: Boolean = true
에서 문서 것 같습니다 ++
반면 더 일반적이다 :::
입니다 List
– 특정. 후자는 다른 기능 언어로 사용되기 때문에 제공됩니까?
답변
유산. 목록은 원래 기능적인 언어로 정의되었습니다.
1 :: 2 :: Nil // a list
list1 ::: list2 // concatenation of two lists
list match {
case head :: tail => "non-empty"
case Nil => "empty"
}
물론 스칼라는 다른 컬렉션을 임시 방식으로 발전시켰다. 2.8이 나왔을 때 코드 재사용 및 일관성있는 API를 극대화하기 위해 컬렉션이 다시 디자인되었으므로 두 컬렉션, 심지어 반복자 ++
를 연결 하는 데 사용할 수 있습니다 . 그러나 목록은 사용되지 않는 하나 또는 두 개를 제외하고 원래 연산자를 유지해야합니다.
답변
항상 사용하십시오 :::
. 효율성과 형식 안전성이라는 두 가지 이유가 있습니다.
능률
x ::: y ::: z
올바른 연관성이 x ++ y ++ z
있기 때문에 보다 빠릅니다 :::
. x ::: y ::: z
는로 해석되며 x ::: (y ::: z)
이는 알고리즘보다 빠릅니다 (x ::: y) ::: z
(후자는 O (| x |) 더 많은 단계 필요).
타입 안전
:::
당신 과 함께 두 개의 연결할 수 있습니다 List
. 를 사용 ++
하면에 컬렉션을 추가 할 수 있습니다 List
.
scala> List(1, 2, 3) ++ "ab"
res0: List[AnyVal] = List(1, 2, 3, a, b)
++
다음과 혼합하기도 쉽습니다 +
.
scala> List(1, 2, 3) + "ab"
res1: String = List(1, 2, 3)ab
답변
:::
++
모든 트래 버터 블과 함께 사용할 수 있지만 목록에서만 작동합니다 . 현재 구현 (2.9.0)에서 ++
다시 내리는 :::
인수도 경우 List
.
답변
다른 점은 첫 번째 문장이 다음과 같이 구문 분석된다는 것입니다.
scala> List(1,2,3).++(List(4,5))
res0: List[Int] = List(1, 2, 3, 4, 5)
두 번째 예는 다음과 같이 구문 분석됩니다.
scala> List(4,5).:::(List(1,2,3))
res1: List[Int] = List(1, 2, 3, 4, 5)
따라서 매크로를 사용하는 경우주의해야합니다.
또한 ++
두 목록에 대해 호출 :::
하지만 목록에서 목록으로 빌더를 갖는 암시 적 값을 요청하므로 더 많은 오버 헤드가 발생합니다. 그러나 마이크로 벤치 마크는 그러한 의미에서 유용한 것을 입증하지 못했습니다. 컴파일러가 그러한 호출을 최적화한다고 생각합니다.
예열 후 마이크로 벤치 마크.
scala>def time(a: => Unit): Long = { val t = System.currentTimeMillis; a; System.currentTimeMillis - t}
scala>def average(a: () => Long) = (for(i<-1 to 100) yield a()).sum/100
scala>average (() => time { (List[Int]() /: (1 to 1000)) { case (l, e) => l ++ List(e) } })
res1: Long = 46
scala>average (() => time { (List[Int]() /: (1 to 1000)) { case (l, e) => l ::: List(e ) } })
res2: Long = 46
Daniel C. Sobrai가 말했듯이을 사용하여 컬렉션의 모든 내용을 목록에 추가 할 수 ++
있지만 목록을 :::
연결하는 것만 가능합니다.