Почему так мало вещей @specialized в стандартной библиотеке Scala? - PullRequest
38 голосов
/ 29 марта 2011

Я искал использование @specialized в исходном коде стандартной библиотеки Scala 2.8.1.Похоже, только несколько черт и классов используют эту аннотацию: Function0, Function1, Function2, Tuple1, Tuple2, Product1, Product2, AbstractFunction0, AbstractFunction1,AbstractFunction2.

Ни один из классов коллекции не является @specialized.Почему бы и нет?Будет ли это генерировать слишком много классов?

Это означает, что использование классов коллекций с примитивными типами очень неэффективно, потому что будет много ненужных коробок и распаковок.

Что наиболее эффективноспособ иметь неизменный список или последовательность (с IndexedSeq характеристиками) Int с, избегая коробок и распаковок?

Ответы [ 3 ]

18 голосов
/ 30 марта 2011

Специализация имеет высокую стоимость по размеру классов, поэтому она должна быть добавлена ​​с тщательным рассмотрением. Я полагаю, что в конкретном случае коллекций влияние будет огромным.

Тем не менее, это постоянное усилие - библиотека Scala едва стала специализированной.

16 голосов
/ 08 марта 2013

Специализированный может быть дорогим ( экспоненциальный ) как по размеру классов, так и по времени компиляции.Это не просто размер, как говорит принятый ответ.

Откройте ваш scala REPL и введите его.

import scala.{specialized => sp}
trait S1[@sp A, @sp B, @sp C, @sp D] { def f(p1:A): Unit }

Извините :-).Это как бомба компилятора.

Теперь давайте возьмем простую черту

trait Foo[Int]{ }

Выше приведено два скомпилированных класса.Foo, чистый интерфейс и Foo $ 1, реализация класса.

Теперь,

trait Foo[@specialized A] { }

Специальный параметр шаблона здесь расширяется / переписывается для 9 различных примитивных типов (void, boolean, byte, char, int, long, short, double, float).Таким образом, в итоге вы получаете 20 классов вместо 2.

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

2 * 10 ^ (без специализированных параметров)

Если вы определяете класс для конкретного примитивного типа, вы должны быть болеепрямо об этом, например,

trait Foo[@specialized(Int) A, @specialized(Int,Double) B] { }

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

Здесь - это разглагольствование Пола Филлипса.

6 голосов
/ 29 марта 2011

Частичный ответ на мой собственный вопрос: я могу обернуть массив в IndexedSeq следующим образом:

import scala.collection.immutable.IndexedSeq

def arrayToIndexedSeq[@specialized(Int) T](array: Array[T]): IndexedSeq[T] = new IndexedSeq[T] {
  def apply(idx: Int): T = array(idx)
  def length: Int = array.length
}

(Конечно, вы можете изменить содержимое, если у вас есть доступ к базовому массиву, но я бы позаботился о том, чтобы массив не передавался другим частям моей программы).

...