REAL GENERICS

2.8’S @SPECIALIZED
        AND
     MANIFESTS
 Enno Runne @ Scala Sweden meeting
   Stockholm, 8th September 2010

                 1
GENERICS BEFORE 2.8
class Container[T](val value: T)
val c = new Container(5)
val i = c.value




                     2
GENERICS BEFORE 2.8
class Container[T](val value: T)
val c = new Container(5)
val i = c.value




                     2
GENERICS BEFORE 2.8
class Container[T](val value: T)
val c = new Container(5)
val i = c.value


Translates with type erasure to
class Container(val value: Object)
val c = new Container(new Integer(5))
val i = c.value.intValue

                            2
TYPE ERASURE


• all
    type parameters are replaced by their lower bound,
  normally java.lang.Object

• all
    JVM base types get boxed into their reference type
  equivalent (and un-boxed on the way out)



                               3
REAL GENERICS


• type variables annotated with @specialized lead to specialized
 classes for base types

• overloaded   methods

• Object   version still exists, type hierarchy



                                    4
REAL GENERICS
class Container[@specialized T](val value: T)
val c = new Container(5)
val i = c.value




                     5
REAL GENERICS
class Container[@specialized T](val value: T)
val c = new Container(5)
val i = c.value




                     5
REAL GENERICS
class Container[@specialized T](val value: T)
val c = new Container(5)
val i = c.value


Translates with Scala 2.8 to
class Container(val value: Int)
val c = new Container(5)                     No boxing
val i = c.value
                                   No un-boxing
                               5
@SPECIALIZED


•   @specialized generates specific classes for every JVM
    base type and for Object

•   @specialized(Int, Double) generates specific classes
    for the listed JVM base types and for Object, the base types
    not listed get boxed and un-boxed


                                  6
@SPECIALIZED
      IN STANDARD LIBRARY

trait Function1[
  @specialized(Int, Long, Float, Double) -T1,
  @specialized(Unit, Boolean, Int, Float, Long,
  Double) +R]



class Range(...) {
  def foreach[@specialized(Unit) U](f: Int => U)
}


                          7
WHAT’S NOT GOOD


• increases   volume of compiled code

• class   and method names become a bit obfuscated in the stack
 trace

• does    not solve array creation issues



                                   8
ARRAYS BEFORE 2.8
class MyArray[T](value: T) {
	 val arr: Array[T]
             = new Array[T](2)
}




                      9
ARRAYS BEFORE 2.8
class MyArray[T](value: T) {
	 val arr: Array[T]
             = new Array[T](2)
}




                      9
ARRAYS BEFORE 2.8
class MyArray[T](value: T) {
	 val arr: Array[T]
                  = new Array[T](2)
}
Translates with type erasure to
class MyArray(value: Object) {
	 val arr: Array[Object]
                  = new Array[Object](2)
}
                            9
ARRAYS BEFORE 2.8
class MyArray[T](value: T) {
	 val arr: Array[T]
                  = new Array[T](2)
}
Translates with type erasure to

                                                     !
                              All array based data
class MyArray(value: Object) { structures used
	 val arr: Array[Object]         Array[Object]

                  = new Array[Object](2)
}
                            9
ARRAYS



• JVM   arrays have a special type hierarchy

•   new Array requires the exact element type to avoid
    runtime type checking



                                 10
2.8 ARRAYS
class MyArray[T](value: T)
           (implicit m: ClassManifest[T]) {
	 val arr: Array[T] = new Array[T](2)
}




                         11
2.8 ARRAYS
class MyArray[T](value: T)
           (implicit m: ClassManifest[T]) {
	 val arr: Array[T] = new Array[T](2)
}




                         11
2.8 ARRAYS
class MyArray[T](value: T)
                (implicit m: ClassManifest[T]) {
	 val arr: Array[T] = new Array[T](2)
}

Translates to
class MyArray(value: Object) {
	 val arr: Object
                 = new Array[runtime type](2)
}

                             11
2.8 ARRAYS


• usenew implicit parameters, compiler passes an extra
 parameter

• extraparameter contains type information required for array
 construction



                              12
2.8 ARRAYS
class MyArray[T](value: T)
            (implicit m: ClassManifest[T]) {
	 val arr: Array[T] = new Array[T](2)
}

Short-cut notation
class MyArray[T : Manifest] {
	 val arr: Array[T] = new Array[T](2)
}



                         13
2.8 ARRAYS
class MyArray[T](value: T)
            (implicit m: ClassManifest[T]) {
	 val arr: Array[T] = new Array[T](2)
}

Short-cut notation
class MyArray[T : Manifest] {
	 val arr: Array[T] = new Array[T](2)
}



                         13
SUMMARY



• @specialized   can avoid boxing/un-boxing be generating sub-
 classes

• Manifests   allow array creation with type parameters




                                 14

Real generics

  • 1.
    REAL GENERICS 2.8’S @SPECIALIZED AND MANIFESTS Enno Runne @ Scala Sweden meeting Stockholm, 8th September 2010 1
  • 2.
    GENERICS BEFORE 2.8 classContainer[T](val value: T) val c = new Container(5) val i = c.value 2
  • 3.
    GENERICS BEFORE 2.8 classContainer[T](val value: T) val c = new Container(5) val i = c.value 2
  • 4.
    GENERICS BEFORE 2.8 classContainer[T](val value: T) val c = new Container(5) val i = c.value Translates with type erasure to class Container(val value: Object) val c = new Container(new Integer(5)) val i = c.value.intValue 2
  • 5.
    TYPE ERASURE • all type parameters are replaced by their lower bound, normally java.lang.Object • all JVM base types get boxed into their reference type equivalent (and un-boxed on the way out) 3
  • 6.
    REAL GENERICS • typevariables annotated with @specialized lead to specialized classes for base types • overloaded methods • Object version still exists, type hierarchy 4
  • 7.
    REAL GENERICS class Container[@specializedT](val value: T) val c = new Container(5) val i = c.value 5
  • 8.
    REAL GENERICS class Container[@specializedT](val value: T) val c = new Container(5) val i = c.value 5
  • 9.
    REAL GENERICS class Container[@specializedT](val value: T) val c = new Container(5) val i = c.value Translates with Scala 2.8 to class Container(val value: Int) val c = new Container(5) No boxing val i = c.value No un-boxing 5
  • 10.
    @SPECIALIZED • @specialized generates specific classes for every JVM base type and for Object • @specialized(Int, Double) generates specific classes for the listed JVM base types and for Object, the base types not listed get boxed and un-boxed 6
  • 11.
    @SPECIALIZED IN STANDARD LIBRARY trait Function1[ @specialized(Int, Long, Float, Double) -T1, @specialized(Unit, Boolean, Int, Float, Long, Double) +R] class Range(...) { def foreach[@specialized(Unit) U](f: Int => U) } 7
  • 12.
    WHAT’S NOT GOOD •increases volume of compiled code • class and method names become a bit obfuscated in the stack trace • does not solve array creation issues 8
  • 13.
    ARRAYS BEFORE 2.8 classMyArray[T](value: T) { val arr: Array[T] = new Array[T](2) } 9
  • 14.
    ARRAYS BEFORE 2.8 classMyArray[T](value: T) { val arr: Array[T] = new Array[T](2) } 9
  • 15.
    ARRAYS BEFORE 2.8 classMyArray[T](value: T) { val arr: Array[T] = new Array[T](2) } Translates with type erasure to class MyArray(value: Object) { val arr: Array[Object] = new Array[Object](2) } 9
  • 16.
    ARRAYS BEFORE 2.8 classMyArray[T](value: T) { val arr: Array[T] = new Array[T](2) } Translates with type erasure to ! All array based data class MyArray(value: Object) { structures used val arr: Array[Object] Array[Object] = new Array[Object](2) } 9
  • 17.
    ARRAYS • JVM arrays have a special type hierarchy • new Array requires the exact element type to avoid runtime type checking 10
  • 18.
    2.8 ARRAYS class MyArray[T](value:T) (implicit m: ClassManifest[T]) { val arr: Array[T] = new Array[T](2) } 11
  • 19.
    2.8 ARRAYS class MyArray[T](value:T) (implicit m: ClassManifest[T]) { val arr: Array[T] = new Array[T](2) } 11
  • 20.
    2.8 ARRAYS class MyArray[T](value:T) (implicit m: ClassManifest[T]) { val arr: Array[T] = new Array[T](2) } Translates to class MyArray(value: Object) { val arr: Object = new Array[runtime type](2) } 11
  • 21.
    2.8 ARRAYS • usenewimplicit parameters, compiler passes an extra parameter • extraparameter contains type information required for array construction 12
  • 22.
    2.8 ARRAYS class MyArray[T](value:T) (implicit m: ClassManifest[T]) { val arr: Array[T] = new Array[T](2) } Short-cut notation class MyArray[T : Manifest] { val arr: Array[T] = new Array[T](2) } 13
  • 23.
    2.8 ARRAYS class MyArray[T](value:T) (implicit m: ClassManifest[T]) { val arr: Array[T] = new Array[T](2) } Short-cut notation class MyArray[T : Manifest] { val arr: Array[T] = new Array[T](2) } 13
  • 24.
    SUMMARY • @specialized can avoid boxing/un-boxing be generating sub- classes • Manifests allow array creation with type parameters 14