Учебник по дизайну коллекций Scala 2.8
следуя из моего затаенного замешательства, какие хорошие ресурсы объясняют, как новый Скала 2.8 библиотека коллекций была структурирована. Мне интересно найти некоторую информацию о том, как следующее сочетается:
- сами классы/черты коллекции (например
List,Iterable) - почему как классы (например,
TraversableLike)
- для чего нужны сопутствующие методы (например,
List.companion) - откуда я знаю что
implicitобъекты находятся в области видимости в заданной точке
1 ответ:
предисловие
здесь 2.8 коллекция проходной Мартином Одерски, который, вероятно, должен быть вашей первой ссылкой. Он был дополнен также с архитектурные заметки, что будет представлять особый интерес для тех, кто хочет создавать свои собственные коллекции.
остальная часть этого ответа была написана задолго до того, как такая вещь существовала (фактически, до того, как сам 2.8.0 был выпущен).
вы можете найдите статью об этом как Scala SID #3. Другие документы в этой области также должны быть интересны людям, заинтересованным в различиях между Scala 2.7 и 2.8.
я буду цитировать из статьи, выборочно, и дополнять некоторые мои мысли. Есть также некоторые изображения, созданные Matthias at decodified.com, и оригинальные файлы SVG можно найти здесь.
классы/черты коллекции сами
на самом деле существует три иерархии признаков для коллекций: одна для изменяемых коллекций, одна для неизменяемых коллекций и одна, которая не делает никаких предположений о коллекциях.
существует также различие между параллельными, серийными и, возможно, параллельными коллекциями, которые были введены с Scala 2.9. Я расскажу о них в следующем разделе. Иерархия, описанная в этом разделе, относится исключительно для непараллельных коллекции.
на следующем рисунке показана неспецифическая иерархия, введенная с помощью Scala 2.8:
все элементы показаны черты. В двух других иерархиях есть также классы, непосредственно наследующие признаки, а также классы, которые могут быть рассматривать как принадлежность к этой иерархии через неявное преобразование в классы-оболочки. Легенду для этих графиков можно найти после них.
график незыблемые иерархии:
график для изменяемой иерархии:
легенда:
вот сокращенное изображение ASCII иерархии коллекции, для тех, кто не может видеть изображения.
Traversable | | Iterable | +------------------+--------------------+ Map Set Seq | | | | +----+----+ +-----+------+ Sorted Map SortedSet BitSet Buffer Vector LinearSeqПараллельные Коллекции
когда Scala 2.9 представила параллельные коллекции, одной из целей дизайна было сделать их использование максимально бесшовным. Проще говоря, один можно заменить непараллельную (последовательную) коллекцию на параллельную и мгновенно пожинать плоды.
однако, поскольку все коллекции до тех пор были последовательными, многие алгоритмы, использующие их, предполагали и зависели от того, что они были последовательный. Параллельные коллекции, подаваемые в методы с такими предположениями, потерпят неудачу. По этой причине вся иерархия описана в предыдущем разделе мандаты последовательной обработки.
два для поддержки параллельных коллекций были созданы новые иерархии.
иерархия параллельных коллекций имеет те же имена для признаков, но предшествует
Par:ParIterable,ParSeq,ParMapиParSet. Обратите внимание, что нетParTraversable, так как любая коллекция, поддерживающая параллельный доступ, способна поддерживать более сильныйParIterableчерта. Он также не имеет некоторых из более специализированных черт, присутствующих в последовательной иерархии. Вся эта иерархия находится под каталогscala.collection.parallel.классы, реализующие параллельные коллекции также отличаются, с
ParHashMapиParHashSetкак для изменяемых, так и для неизменяемых параллельных коллекций, плюсParRangeиParVectorреализацияimmutable.ParSeqиParArrayреализацияmutable.ParSeq.также существует другая иерархия, которая отражает черты последовательных и параллельных коллекций, но с префиксом
Gen:GenTraversable,GenIterable,GenSeq,GenMapиGenSet. Эти черты родителям как для параллельных, так и для серийных коллекций. Это означает, что метод принимаетSeqне может получить параллельную коллекцию, но метод принятияGenSeqпредполагается работа как с последовательными, так и с параллельными коллекциями.учитывая то, как эти иерархии были структурированы, код, написанный для Scala 2.8, был полностью совместим с Scala 2.9 и требовал последовательного поведения. Без перезаписи он не может использовать преимущества параллельных коллекций, но необходимые изменения очень малы.
Использование Параллельных Коллекций
любую коллекцию можно преобразовать в параллельную, вызвав метод
parна нем. Аналогично, любая коллекция может быть преобразована в последовательную путем вызова методаseqна нем.если коллекция уже была запрошена (параллельная или последовательная), преобразование не будет выполнено. Если кто-то звонит
seqна параллельной коллекции илиparна серийный коллекция, однако, будет создана новая коллекция с запрошенной характеристикой.не путай
seq, который превращает коллекцию в непараллельную коллекцию, сtoSeq, который возвращает aSeqсоздается из элементов коллекции. ЗвонюtoSeqна параллельной коллекции вернет aParSeq, не серийная коллекция.Основные Черты
в то время как есть много реализующих классов и подзаголовков, есть некоторые основные черты в иерархии, каждая из которых предоставляет больше методов или более конкретные гарантии, но уменьшает количество классов, которые могут их реализовать.
в следующих разделах я дам краткое описание основных черты и идеи.
Trait TraversableOnce
эта черта очень похожа на черту
Traversableописано ниже, но с ограничением, что вы можете использовать только его один раз. Что есть, любые методы, вызываемые наTraversableOnceмая сделать его непригодным для использования.это ограничение делает возможным совместное использование одних и тех же методов между коллекциями и
Iterator. Это делает возможным для метода, который работает сIteratorа не черезIterator-конкретные методы, чтобы на самом деле иметь возможность работать с любой коллекцией вообще, плюс итераторы, если переписаны принятьTraversableOnce., потому что
TraversableOnceобъединяет коллекции и итераторы, it не отображается на предыдущих графиках,которые касаются только коллекций.Черта Проходимым
в верхней части коллекция иерархия признака
Traversable. Его единственная абстрактная операция -def foreach[U](f: Elem => U)операция предназначена для обхода всех элементов коллекции и применения данной операции f к каждому элемент. Приложение выполняется только для его побочного эффекта; на самом деле любой результат функции f отбрасывается инструкция foreach.
проходимые объекты могут быть конечными или бесконечными. Примером бесконечного проходимого объекта является поток натуральных чисел
Stream.from(0). МетодhasDefiniteSizeуказывает, возможно ли создание коллекции бесконечный. ЕслиhasDefiniteSizeвозвращает true, коллекция, безусловно, конечна. Если он возвращает false, то коллекция еще не была полностью разработана, поэтому она может быть бесконечной или конечной.этот класс определяет методы, которые могут быть эффективно реализовано в терминах
foreach(более 40 из них).Черта Iterable
эта черта объявляет абстрактный метод
iteratorэто возвращает итератор, который дает все элементы коллекции один за другим. ЭлементforeachметодIterableреализуется в терминахiterator. ПодклассыIterableчасто переопределение оператора foreach с прямым реализации для повышения эффективности.класс
Iterableтакже добавляет некоторые менее часто используемые методыTraversable, которым может быть эффективно реализован только в том случае, еслиiteratorдоступно. Они кратко излагаются ниже.xs.iterator An iterator that yields every element in xs, in the same order as foreach traverses elements. xs takeRight n A collection consisting of the last n elements of xs (or, some arbitrary n elements, if no order is defined). xs dropRight n The rest of the collection except xs takeRight n. xs sameElements ys A test whether xs and ys contain the same elements in the same orderДругие Особенности
после
Iterableесть три основные черты, которые наследуют от него:Seq,SetиMap. У всех троих естьapplyметод и все три использовать тегPartialFunctionчерта, но смыслapplyотличается в каждом случае.я доверяю смыслу
Seq,SetиMapинтуитивно понятен. После они, классы разбиваются на конкретные реализации, которые предлагают определенные гарантии в отношении производительности, и методы, которые он делает доступными в результате этого. Также доступны некоторые черты с дальнейшими уточнениями, такие какLinearSeq,IndexedSeqиSortedSet.список ниже может быть улучшена. Оставьте комментарий с предложениями, и я это исправлю.
базовые классы и черт
Traversable-- Basic класс коллекции. Может быть реализован только сforeach.
TraversableProxy-- прокси дляTraversable. Просто точкаselfв настоящий сборник.TraversableView-- A проходимый с некоторыми нестрогими методами.TraversableForwarder-- пересылает большинство методов вunderlying, за исключениемtoString,hashCode,equals,stringPrefix,newBuilder,viewи все вызовы, создающие новый итерационный объект того же типа.mutable.Traversableиimmutable.Traversable-- то же самое вещь какTraversable, но ограничение типа коллекции.- другие особые случаи
Iterableклассов, напримерMetaDataсуществует.Iterable-- коллекция, для которойIteratorможет быть создан (черезiterator).
IterableProxy,IterableView,mutableиimmutable.Iterable.Iterator-- черта, которая не является потомкомTraversable. ОпределитьnextиhasNext.
CountedIterator-- AnIteratorопределениеcount, который возвращает элементы до сих пор.BufferedIterator-- определяетhead, который возвращает следующий элемент, не потребляя его.- другие особые случаи
Iteratorклассов, напримерSourceсуществует.Карты
Map-- AnIterableнаTuple2, который также предоставляет методы для получения значение (второй элемент кортежа) задается ключом (первый элемент кортежа). РасширяетсяPartialFunctionкак хорошо.
MapProxy-- AProxyнаMap.DefaultMap-- черта, реализующая некоторые изMapабстрактные методы.SortedMap-- AMapчьи ключи сортируются.
immutable.SortMap
immutable.TreeMap-- реализация классаimmutable.SortedMap.immutable.Map
immutable.MapProxyimmutable.HashMap-- класс, реализующийimmutable.Mapчерез ключ хеширования.immutable.IntMap-- класс, реализующийimmutable.Mapспециализированных дляIntключи. Использует дерево, основанное на двоичных цифрах ключей.immutable.ListMap-- класс, реализующийimmutable.Mapчерез списки.immutable.LongMap-- реализация классаimmutable.Mapспециализированных дляLongключи. СмотритеIntMap.- есть дополнительные классы, оптимизированные для определенного количества элементов.
mutable.Map
mutable.HashMap-- класс, реализующийmutable.Mapчерез ключ хеширования.mutable.ImmutableMapAdaptor-- класс, реализующий amutable.Mapиз существующегоimmutable.Map.mutable.LinkedHashMap-- ?mutable.ListMap-- реализация классаmutable.Mapчерез списки.mutable.MultiMap-- класс, принимающий более одного отдельного значения для каждого ключа.mutable.ObservableMap-- A mixin, который при смешивании сMap, публикует события для наблюдателей черезPublisherинтерфейс.mutable.OpenHashMap-- класс, основанный на открытом алгоритме хэширования.mutable.SynchronizedMap-- A mixin который должен быть смешан сMapчтобы предоставить его версию с синхронизированные методы.mutable.MapProxy.Последовательности
Seq-- последовательность элементов. Предполагается четко определенный размер и повторение элементов. РасширяетсяPartialFunctionкак хорошо.
IndexedSeq-- последовательности, которые поддерживают доступ к элементам O(1) и вычисление длины O(1).
IndexedSeqViewimmutable.PagedSeq-- реализацияIndexedSeqгде элементы создаются по требованию функцией, переданной через конструктор.immutable.IndexedSeq
immutable.Range-- разделенная последовательность целых чисел, замкнутая на нижнем конце, открытая на верхнем конце и с шагом.
immutable.Range.Inclusive-- ARangeзакрыт на верхнем конце, а также.immutable.Range.ByOne-- ARangeчей Шаг 1.immutable.NumericRange-- более общая версияRange, который работает с любымIntegral.
immutable.NumericRange.Inclusive,immutable.NumericRange.Exclusive.immutable.WrappedString,immutable.RichString-- обертки, которые позволяют видетьStringкакSeq[Char], сохраняя при этомStringметоды. Я не уверен, в чем разница между ними.mutable.IndexedSeq
mutable.GenericArray-- AnSeqмассив как структура. Обратите внимание, что "класс"Arrayэто JavaArray, который является скорее методом хранения памяти, чем классом.mutable.ResizableArray-- внутренний класс, используемый классами на основе изменяемых массивов.mutable.PriorityQueue,mutable.SynchronizedPriorityQueue-- классы, реализующие приоритетные очереди -- очереди, в которых элементы удаляются в соответствии сOrderingво-первых, и порядок очереди в последнюю очередь.mutable.PriorityQueueProxy-- абстрактноеProxyдля aPriorityQueue.LinearSeq-- черта для линейных последовательностей, с эффективным временем дляisEmpty,headиtail.
immutable.LinearSeq
immutable.List-- неизменяемая, односвязная реализация списка.immutable.Stream-- ленивый-список. Его элементы вычисляются только по требованию, но запоминаются (хранятся в памяти) впоследствии. Это может быть теоретически бесконечный.mutable.LinearSeq
mutable.DoublyLinkedList-- список с изменяемымprev,head(elem) иtail(next).mutable.LinkedList-- список с изменяемымhead(elem) иtail(next).mutable.MutableList-- класс, используемый внутри для реализации классов на основе изменяемых списков.
mutable.Queue,mutable.QueueProxy-- структура данных, оптимизированная для FIFO (First-In, Первый выход) операции.mutable.QueueProxy-- AProxyнаmutable.Queue.SeqProxy,SeqView,SeqForwarderimmutable.Seq
immutable.Queue-- класс, реализующий оптимизированную по FIFO (First-In, First-Out) структуру данных. Нет общего суперкласса, какmutableиimmutableочереди.immutable.Stack-- класс, реализующий a ЛИФО-оптимизирован (последний в, первым вышел) структура данных. Нет общего суперкласса, какmutableimmutableстеки.immutable.Vector-- ?scala.xml.NodeSeq-- специализированный класс XML, который расширяетimmutable.Seq.immutable.IndexedSeq-- как показано выше.immutable.LinearSeq-- как показано выше.mutable.ArrayStack-- класс, реализующий оптимизированную для LIFO структуру данных с использованием массивов. Якобы значительно быстрее чем обычный стек.mutable.Stack,mutable.SynchronizedStack-- классы, реализующие оптимизированную для LIFO структуру данных.mutable.StackProxy-- AProxyнаmutable.Stack..mutable.Seq
mutable.Buffer-- последовательность элементов, которые могут быть изменены путем добавления, добавления или вставки новых элементов.
mutable.ArrayBuffer-- реализацияmutable.Bufferкласс, с постоянным амортизированным временем для добавления, обновления и случайного операции доступа. Он имеет некоторые специализированные подклассы, такие какNodeBuffer.mutable.BufferProxy,mutable.SynchronizedBuffer.mutable.ListBuffer-- буфер, поддерживаемый списком. Он обеспечивает постоянное время добавления и добавления, причем большинство других операций являются линейными.mutable.ObservableBuffer-- A mixin черта, которая, при смешивании сBuffer, обеспечивает события уведомления черезPublisherинтерфейсы.mutable.IndexedSeq-- как видно выше.mutable.LinearSeq-- как показано выше.Наборы
Set-- набор-это коллекция, которая включает в себя не более одного объекта.
BitSet-- набор целых чисел, хранящихся в виде битов.
immutable.BitSetmutable.BitSetSortedSet-- набор, элементами которого являются упорядоченный.
immutable.SortedSet
immutable.TreeSet-- реализация aSortedSetна основе дерева.SetProxy-- AProxyнаSet.immutable.Set
immutable.HashSet-- реализацияSetна основе хеширования элементов.immutable.ListSet-- реализацияSetна основе списков.- существует дополнительный набор классов чтобы обеспечить оптимизированные реализации для наборов от 0 до 4 элементов.
immutable.SetProxy-- AProxyдля неизменяемогоSet.mutable.Set
mutable.HashSet-- реализацияSetна основе хеширования элементов.mutable.ImmutableSetAdaptor-- класс, реализующий изменяемыйSetот неизменногоSet.LinkedHashSet-- реализацияSetна основе списки.ObservableSet-- A mixin черта, которая, при смешивании сSet, обеспечивает события уведомления черезPublisherинтерфейс.SetProxy-- AProxyнаSet.SynchronizedSet-- A mixin черта, которая, при смешивании сSet, обеспечивает события уведомления черезPublisherвзаимодействие.
- почему существуют подобные классы (например, TraversableLike)
это было сделано для достижения максимального повторного использования кода. Бетон generic реализация для классов с определенной структурой (проходимая, карта и т. д.) выполняется в подобных классах. Классы, предназначенные для общего потребления, затем переопределить некоторые методы, которые могут быть optmized.
- для чего предназначены сопутствующие методы (например, список.компаньон)
Строитель для классов, т. е. объект, который знает, как создавать экземпляры этого класса таким образом, который может быть использован такими методами, как
map, создается методом в сопутствующем объекте. Итак, чтобы построить объект типа X, мне нужно получить этот строитель из сопутствующего объекта X. К сожалению, в Scala нет способа получить из класса X объект X. Из-за этого существует метод, определенный в каждом экземпляре X,companion, который возвращает сопутствующий объект класса X.хотя такой метод может быть использован в обычных программах, его цель - разрешить повторное использование кода в библиотеке коллекций.
- как я знаю, какие неявные объекты находятся в области видимости в данной точке
вы не должны заботиться об этом. Они подразумеваются именно так, чтобы вы этого не делали необходимо выяснить, как заставить его работать.
эти импликаты существуют для того, чтобы методы в коллекциях определялись в родительских классах, но все же возвращали коллекцию того же типа. Например,
mapметод определяется наTraversableLike, а если вы использовали наListвы получаетеListобратно.




Comments