Why are so few things @specialized in Scala's standard library?

后端 未结 3 865
夕颜
夕颜 2021-02-01 01:46

I\'ve searched for the use of @specialized in the source code of the standard library of Scala 2.8.1. It looks like only a handful of traits and classes use this an

相关标签:
3条回答
  • 2021-02-01 02:20

    Specialized can be expensive ( exponential ) in both size of classes and compile time. Its not just the size like the accepted answer says.

    Open your scala REPL and type this.

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

    Sorry :-). Its like a compiler bomb.

    Now, lets take a simple trait

    trait Foo[Int]{ }
    

    The above will result in two compiled classes. Foo, the pure interface and Foo$1, the class implementation.

    Now,

    trait Foo[@specialized A] { }
    

    A specialized template parameter here gets expanded/rewritten for 9 different primitive types ( void, boolean, byte, char, int, long, short, double, float ). So, basically you end up with 20 classes instead of 2.

    Going back to the trait with 5 specialized template parameters, the classes get generated for every combination of possible primitive types. i.e its exponential in complexity.

    2 * 10 ^ (no of specialized parameters)

    If you are defining a class for a specific primitive type, you should be more explicit about it such as

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

    Understandably one has to be frugal using specialized when building general purpose libraries.

    Here is Paul Phillips ranting about it.

    0 讨论(0)
  • 2021-02-01 02:25

    Specialization has a high cost on the size of classes, so it must be added with careful consideration. In the particular case of collections, I imagine the impact will be huge.

    Still, it is an on-going effort -- Scala library has barely started to be specialized.

    0 讨论(0)
  • 2021-02-01 02:45

    Partial answer to my own question: I can wrap an array in an IndexedSeq like this:

    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
    }
    

    (Ofcourse you could still modify the contents if you have access to the underlying array, but I would make sure that the array isn't passed to other parts of my program).

    0 讨论(0)
提交回复
热议问题