32
Value Classes in Scala Lukas Rytz, Typesafe

Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Embed Size (px)

Citation preview

Page 1: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Value Classes in Scala

Lukas Rytz, Typesafe

Page 2: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Value Classes in Scala

• Introduced in Scala 2.10.0 (January 2013)

• Release Notes:

2

,A class may now extend AnyVal to make it behave like a struct type (restrictions apply).

Page 3: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Agenda

• Introduction to value classes

• Compiler transformation: an example

• Value classes in Scala's type hierarchy

• Limitations and feature interactions

3

Page 4: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Main Idea

• Value class instances are inlined: represented at runtime as their fields

↣ Space: no object header, no work for GC

↣ Locality: no pointer chasing

↣ Convenient for programmers (normal classes)

4

Page 5: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Implications of this Representation

• Values (value class instances) have no object identity

↣ No locking on values, identityHashCode, ...

• Fields of values are immutable

↣ Values are passed "by value" (copied)

5

Page 6: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Some Use Cases• Extension methods without overhead

• Bit fields: Mode in scalac's type checker, Flags

• Semantic primitives: units of measure

• New numeric types like Complex ↣ FastComplex in spire: two floats in one long ↣ (Scala has only single-field value classes)

6

Page 7: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Agenda

• Introduction to value classes

• Compiler transformation: an example

• Value classes in Scala's type hierarchy

• Limitations and feature interactions

7

Page 8: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Example: Extension Method

8

object  Predef  {      implicit  class  Ar[A](private  val  a:  A)      extends  AnyVal  {          def  -­‐>  [B](b:  B):  Tuple2[A,  B]  =  Tuple2(a,  b)      }  }  !scala>  "jan"  -­‐>  "january"  res0:  (String,  String)  =  (jan,january)

Page 9: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Example: extension method

9

object  Predef  {      implicit  class  Ar[A](private  val  a:  A)      extends  AnyVal  {          def  -­‐>  [B](b:  B):  Tuple2[A,  B]  =  Tuple2(a,  b)      }  }  !scala>  "jan"  -­‐>  "january"  res0:  (String,  String)  =  (jan,january)

Page 10: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

-Xprint:parser

10

implicit  class  Ar[A]  extends  AnyVal  {      private  val  a:  A  =  _      def  <init>(a:  A)  =  super.<init>()      def  -­‐>[B](b:  B):  Tuple2[A,  B]  =  Tuple2(a,  b)  }

Parser

Type Checker

Extension Methods

Erasure

Page 11: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

11

final  class  Ar[A]  extends  AnyVal  {      private[this]  val  a:  A  =  _      private  def  a:  A  =  this.a  !    def  <init>(a:  A):  Ar[A]  =  super.<init>()      def  -­‐>[B](b:  B):  (A,  B)  =  Tuple2.apply[A,  B](a,  b)  !    override  def  hashCode():  Int  =  ...      override  def  equals(x$1:  Any):  Boolean  =  ...  }  !implicit  def  Ar[A](a:  A):  Ar[A]  =  new  Ar[A](a)

-Xprint:typerParser

Type Checker

Extension Methods

Erasure

Page 12: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

12

final  class  Ar[A]  extends  AnyVal  {      //  Field,  constructor  !    def  -­‐>[B](b:  B):  (A,  B)  =          Ar.-­‐>$extension[B,  A](this)(b)  !    //  Similar  for  hashCode,  equals  }  !object  Ar  extends  AnyRef  {      def  -­‐>$extension[B,  A]($this:  Ar[A])(b:  B):  (A,  B)  =          Tuple2.apply[A,  B]($this.a,  b)  !    //  similar  for  hashCode,  equals  }  !implicit  def  Ar[A](a:  A):  Ar[A]  =  new  Ar[A](a)

-Xprint:extmethodsParser

Type Checker

Extension Methods

Erasure

Page 13: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

final  class  Ar  extends  Object  {      private[this]  val  a:  Object  =  _      final  def  a():  Object  =  this.a      def  <init>(a:  Object):  Ar  =  super.<init>()      def  -­‐>(b:  Object):  Tuple2  =  Ar.-­‐>$extension(this.a(),  b)  }  !!object  Ar  extends  Object  {      def  -­‐>$extension($this:  Object,  b:  Object):  Tuple2  =          new  Tuple2($this,  b)  }  !!implicit  def  Ar(a:  Object):  Object  =  a

-Xprint:posterasure

13

Ar[A] ⟹ A ⟹ Object

new  Ar(a) ⟹ a

Ar[A] ⟹ ArA ⟹ Object

$this.a() ⟹ $this

Parser

Type Checker

Extension Methods

Erasure

Page 14: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Example: extension method

14

object  Predef  {      implicit  class  Ar[A](private  val  a:  A)      extends  AnyVal  {          def  -­‐>  [B](b:  B):  Tuple2[A,  B]  =  Tuple2(a,  b)      }  }  !scala>  "jan"  -­‐>  "january"  res0:  (String,  String)  =  (jan,january)

Page 15: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Client Code

15

class  C  {  def  f  =  "jan"  -­‐>  "january"  }  !//  After  typer  class  C  extends  AnyRef  {      def  f:  Tuple2[String,  String]  =          Ar[String]("jan").-­‐>[String]("january")  }  !//  After  erasure  class  C  extends  Object  {      def  f():  Tuple2  =          ArrowAssoc.-­‐>$extension(Ar("jan"),  "january")  }

No boxing!

Page 16: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Agenda

• Introduction to value classes

• Compiler transformation: an example

• Value classes in Scala's type hierarchy

• Limitations and feature interactions

16

Page 17: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Defining Value Classes• No fields, only (one single) class parameter

• No initializer statements

• The wrapped value may not be a value class ↣ Not yet implemented

• hashCode and equals cannot be user-defined

• Value classes extend AnyVal

17

Page 18: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Type Hierarchy

18

AnyVal

Any

AnyRef (j.l.Object)

Int

Boolean

Classes, Traits

Nothing

Null

Value Classes

Page 19: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Type Hierarchy

19

AnyVal

Any

AnyRef (j.l.Object)

Int

Boolean

Classes, Traits

Nothing

Null

Value Classes

synchronizedcannot be null

Page 20: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Extending Traits

• Traits may have fields, initializers ↣ Not suitable as parents for value classes

• Value classes can extend universal traits ↣ Universal traits extend Any

↣ No fields, no synchronization

20

Page 21: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Type Hierarchy

21

AnyVal

Any

AnyRef (j.l.Object)

Int

Boolean

Universal Traits

Classes, Traits

Nothing

Null

Value Classes

synchronizedcannot be null

Page 22: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Agenda

• Introduction to value classes

• Compiler transformation: an example

• Value classes in Scala's type hierarchy

• Limitations and feature interactions

22

Page 23: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Boxing

23

• Assigning a value to a supertype (parent trait, AnyVal, Any)

• Generics: no specialization for value classes (yet) ↣ For data structures and methods

• Values stored in arrays ☹

↣ Need meters.isInstanceOf[Array[Meter]]

Page 24: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Trait Method Calls

24

trait  Super  extends  Any  {      def  x:  Int      def  f  =  this.x  }  !def  t1(s:  Super)  =  s.f  !!class  Value(val  x:  Int)  extends  AnyVal  with  Super  !def  t2(v:  Value)  =  v.f

Needs to be a virtual call. Requires an object.

Code of f (compiled separately) assumes existence of an instance

Page 25: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Performance Model• Boxing is implicit: the code does not reveal the

representation

• Difficult for users: requires knowledge about the limitations

• Scala favours uniformity in other places, e.g., ↣ while / for loops ↣ Collections of primitives

25

Page 26: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Overloading Restrictions

26

class  Meter(val  x:  Double)  extends  AnyVal  class  Mile(val  x:  Double)  extends  AnyVal  !trait  Distance  {      def  add(m:  Meter):  Distance      def  add(m:  Mile):  Distance  }  !error:  double  definition:      def  add(m:  Meter):  Distance      def  add(m:  Mile):  Distance  have  same  type  after  erasure:  (m:  Double)Distance

Page 27: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Manifestation at Bridges

27

class  C[T](val  x:  T)  extends  AnyVal  !trait  T[A]  {  def  f:  A  }  !class  K  extends  T[C[Object]]  {      def  f:  C[Object]  =  ..  }  !!error:  bridge  generated  for  member                                  method  f:  ()C[Object]  in  class  K  which  overrides  method  f:  ()A  in  trait  T  clashes  with  definition  of  the  member  itself;  both  have  erased  type  ()Object

Page 28: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Extending Java Interfaces

28

https://groups.google.com/forum/#!topic/scala-internals/12h2TgDFnDM https://groups.google.com/forum/#!topic/scala-internals/jsVlJI4H5OQ

• Java interfaces in Scala are subtypes of AnyRef

• Making them universal (extend Any) is source-incompatible  def  f(i:  JavaIface)  =  i.synchronized  {  ..  }  

• Hack for Serializable, Comparable

↣ Allow case classes to be value classes ↣ Scala library has value classes extending Comparable

Page 29: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Option[T] value class?

29

scala>  Set[String](null,  "hi")  find  (_  ==  null)  res:  Option[String]  =  Some(null)

https://groups.google.com/forum/#!topic/scala-language/Mz_VoJdJf1w

null None Some(null) Some(x)

null x

Page 30: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Feature Interactions in the Compiler

• Implementation in the compiler is difficult at the edges

• Examples from the issue tracker ↣ VCs + type bounds: compiler crash (SI-6304) ↣ VC method with lazy val: compiler crash (SI-6358) ↣ VC with private[this] method: compiler crash

(SI-7019)

30

Page 31: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Future: Multiple Fields

• Doable on today's VM

• Investment vs. return, given the limitations ↣ Returns require boxing (or other tricks) ↣ Boxing in arrays ↣ Writes to fields are not atomic

31

Page 32: Value Classes in Scala - · PDF fileValue Classes in Scala • Introduced in Scala 2.10.0 (January 2013) • Release Notes: 2, A class may now extend AnyVal to make it behave like

Future

• Integrate with specialization

• Re-implement on top of the VM support ↣ Profit: arrays of values, return multiple values ↣ Compatibility with the rest of the ecosystem

(e.g., reflection)

32