Списки в Scala - плюс двоеточие против двойного двоеточия (+: vs::)

Я немного запутался в +: и ::, которые доступны.

Похоже, оба они дают одинаковые результаты.

scala> List(1,2,3)
res0: List[Int] = List(1, 2, 3)

scala> 0 +: res0
res1: List[Int] = List(0, 1, 2, 3)

scala> 0 :: res0
res2: List[Int] = List(0, 1, 2, 3)

Для моего исходного кода исходный код для обоих методов выглядит аналогичным (метод плюс-двоеточие имеет дополнительное условие для дженериков с использованием заводов-застройщиков).

Какой из этих методов следует использовать и когда?

Ответ 1

+: работает с любым типом коллекции, а :: - это конкретная реализация для List. Если вы внимательно посмотрите на источник для +:, вы заметите, что на самом деле он вызывает ::, когда ожидаемый тип возвращаемого значения List, Это связано с тем, что :: более эффективно реализуется в случае List: он просто соединяет новую голову с существующим списком и возвращает результат, который является операцией с постоянным временем, в отличие от линейного копирования всей коллекции в общий случай +:.

+:, с другой стороны, принимает CanBuildFrom, поэтому вы можете притворяться (хотя и не выглядящим так красиво в этом случае), например:

val foo: Array[String] = List("foo").+:("bar")(breakOut)

(В этом конкретном случае это довольно бесполезно, так как вы можете начать с нужного типа, но идея состоит в том, что вы можете добавить и элемент в коллекцию и изменить его тип в одном "go", избегая дополнительного копия).