[list] 스칼라리스트 연결, ::: vs ++

스칼라에서 목록 :::++연결 목록 간에 차이점이 있습니까?

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가 말했듯이을 사용하여 컬렉션의 모든 내용을 목록에 추가 할 수 ++있지만 목록을 :::연결하는 것만 가능합니다.


답변