Nano Hash - криптовалюты, майнинг, программирование

В чем разница между `::` и `+:` для добавления в список)?

List имеет 2 метода, которые указаны для добавления элемента в (неизменяемый) список:

  • +: (реализация Seq.+:) и
  • :: (определено только в List)

+: технически имеет более общую сигнатуру типа —

def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[List[A], B, That]): That
def ::[B >: A](x: B): List[B]

— но игнорируя неявное, которое, согласно сообщению документа, просто требует, чтобы That было List[B], подписи эквивалентны.

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

Редактировать

Существует также экстрактор для :: в сопоставлении с образцом, но меня интересуют именно эти методы.

См. также: Конкатенация списков Scala, ::: vs ++


Ответы:


1

Лучший способ определить разницу между обоими методами — посмотреть исходный код.

источник из :::

def ::[B >: A] (x: B): List[B] =
  new scala.collection.immutable.::(x, this)

источник из +::

override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[List[A], B, That]): That = bf match {
  case _: List.GenericCanBuildFrom[_] => (elem :: this).asInstanceOf[That]
  case _ => super.+:(elem)(bf)
}

Как видите, для List оба метода делают одно и то же (компилятор выберет List.canBuildFrom для аргумента CanBuildFrom).

Итак, какой метод использовать? Обычно выбирают интерфейс (+:), а не реализацию (::), но поскольку List является общей структурой данных в функциональных языках, у нее есть свои широко используемые методы. Многие алгоритмы построены так, как работает List. Например, вы найдете множество методов, которые добавляют отдельные элементы к List или вызывают удобные методы head или tail, потому что все эти операции O(1). Поэтому, если вы работаете локально с List (внутри отдельных методов или классов), нет проблем выбрать методы, специфичные для List. Но если вы хотите общаться между классами, то есть вы хотите написать какие-то интерфейсы, вам следует выбрать более общий интерфейс Seq.

05.08.2012
  • Но почему они выставили List.:: на всеобщее обозрение? Похоже, они могли реализовать все в List.+:, заменив вызов :: в первом case на new scala.collection.immutable.::(elem, this). 05.08.2012
  • @Mechanicalsnail Я полагаю, что это было сделано для того, чтобы было очевидно, что алгоритм опирается на List, а не на общий Seq по причинам, уже объясненным sschaef. Кроме того, согласно этой таблице, существуют огромные различия в том, как каждая реализация Seq предназначена для использования. Например, +: будет ужасно работать с Queue, а использование :: защитит вас от случайной передачи его вашему алгоритму. 05.08.2012
  • @Mechanicalsnail: Сообщество Scala уже обсуждало смысл ::. Еще один часто упоминаемый момент заключается в том, что существование :: имеет исторические причины. В первых версиях Scala не было таких обобщенных коллекций, как сегодня. Кроме того, в семействе функциональных языков ML есть : в качестве оператора добавления к списку. Поэтому его происхождение гораздо глубже, как может показаться. 05.08.2012

  • 2

    +: является более общим, поскольку он позволяет типу результата отличаться от типа объекта, для которого он вызывается. Например:

    scala> Range(1,4).+:(0)
    res7: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 2, 3)
    
    05.08.2012
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..