Один из самых мощных шаблонов, доступных в Scala, - это шаблон шаблон enrich-my-library *, который использует неявные преобразования в , появляются для добавления методов в существующие классы без необходимости динамического разрешения методов. Например, если бы мы хотели, чтобы все строки имели метод пробелы
, который подсчитывает, сколько в них пробелов, мы могли бы:
class SpaceCounter(s: String) {
def spaces = s.count(_.isWhitespace)
}
implicit def string_counts_spaces(s: String) = new SpaceCounter(s)
scala> "How many spaces do I have?".spaces
res1: Int = 5
К сожалению, этот шаблон вызывает проблемы при работе с универсальными коллекциями. Например, был задан ряд вопросов о группировке элементов последовательно с коллекциями . В нем нет ничего встроенного, что работало бы за один раз, поэтому это кажется идеальным кандидатом для шаблона обогащения моей библиотеки с использованием общей коллекции C
и универсального типа элемента A
:
class SequentiallyGroupingCollection[A, C[A] <: Seq[A]](ca: C[A]) {
def groupIdentical: C[C[A]] = {
if (ca.isEmpty) C.empty[C[A]]
else {
val first = ca.head
val (same,rest) = ca.span(_ == first)
same +: (new SequentiallyGroupingCollection(rest)).groupIdentical
}
}
}
кроме, конечно, не работает . REPL сообщает нам:
:12: error: not found: value C
if (ca.isEmpty) C.empty[C[A]]
^
:16: error: type mismatch;
found : Seq[Seq[A]]
required: C[C[A]]
same +: (new SequentiallyGroupingCollection(rest)).groupIdentical
^
Есть две проблемы: как получить C [C [A]]
из пустого списка C [A]
(или из воздуха )? И как получить C [C [A]]
обратно из той же строки +:
вместо Seq [Seq [A]]
?
* Ранее известный как pimp-my-library.