KEMBAR78
Introduction to Scala for Data Science Technology | PPT
Traits
 Similar to interfaces in Java
 They may have implementations of methods
 But can’t contain state
 Can be multiply inherited from
Example of traits
trait Similarity {
def isSimilar(x: Any): Boolean;
def isNotSimilar(x: Any): Boolean = !isSimilar(x);
}
class Point(xc: Int, yc: Int) with Similarity {
var x: Int = xc;
var y: Int = yc;
def isSimilar(obj: Any) =
obj.isInstanceOf[Point] &&
obj.asInstanceOf[Point].x == x;
}
Mixin class composition
 Basic inheritance model is single inheritance
 But mixin classes allow more flexibility
class Point2D(xc: Int, yc: Int) {
val x = xc;
val y = yc;
// methods for manipulating Point2Ds
}
class ColoredPoint2D(u: Int, v: Int, c: String)
extends Point2D(u, v) {
var color = c;
def setColor(newCol: String): Unit = color = newCol;
}
Mixin class composition example
ColoredPoint2D
Point2D
class Point3D(xc: Int, yc: Int, zc: Int)
extends Point2D(xc, yc) {
val z = zc;
// code for manipulating Point3Ds
}
Point3D
class ColoredPoint3D(xc: Int, yc: Int, zc: Int, col: String)
extends Point3D(xc, yc, zc)
with ColoredPoint2D(xc, yc, col);
ColoredPoint3D
ColoredPoint2D
Mixin class composition
 Mixin composition adds members explicitly
defined in ColoredPoint2D
(members that weren’t inherited)
 Mixing a class C into another class D is legal
only as long as D’s superclass is a subclass of
C’s superclass.
 i.e., D must inherit at least everything that C
inherited
 Why?
Mixin class composition
 Remember that only members explicitly
defined in ColoredPoint2D are mixin
inherited
 So, if those members refer to definitions
that were inherited from Point2D, they had
better exist in ColoredPoint3D
 They do, since
ColoredPoint3D extends Point3D
which extends Point2D
Views
 Defines a coercion from one type to another
 Similar to conversion operators in C++/C#
trait Set {
def include(x: int): Set;
def contains(x: int): boolean
}
def view(list: List) : Set = new Set {
def include(x: int): Set = x prepend xs;
def contains(x: int): boolean =
!isEmpty &&
(list.head == x || list.tail contains x)
}
Views
 Views are inserted automatically by the Scala
compiler
 If e is of type T then a view is applied to e if:
 expected type of e is not T (or a supertype)
 a member selected from e is not a member of T
 Compiler uses only views in scope
Suppose xs : List and view above is in scope
val s: Set = xs;
xs contains x
val s: Set = view(xs);
view(xs) contains x
Compound types motivation
def cloneAndReset(obj: ?): Cloneable = {
val cloned = obj.clone();
obj.reset;
cloned
}
trait Resetable {
def reset: Unit;
}
trait Cloneable {
def clone();
}
Compound types
 In Java, the “solution” is:
interface CloneableAndResetable extends
Cloneable, Resetable
 But if the original object did not use the
CloneableAndResetable interface, it won’t
work
 Scala solution: use compound types (also
called intersection types)
def cloneAndReset(obj: Cloneable with Resetable):
Cloneable = {
...
}
Variance annotations
class Array[a] {
def get(index: int): a
def set(index: int, elem: a): unit;
}
 Array[String] is not a subtype of Array[Any]
 If it were, we could do this:
val x = new Array[String](1);
val y : Array[Any] = x;
y.set(0, new FooBar());
// just stored a FooBar in a String array!
Variance Annotations
 Covariance is ok with functional data structures
trait GenList[+T] {
def isEmpty: boolean;
def head: T;
def tail: GenList[T]
}
object Empty extends GenList[All] {
def isEmpty: boolean = true;
def head: All = throw new Error("Empty.head");
def tail: List[All] = throw new Error("Empty.tail");
}
class Cons[+T](x: T, xs: GenList[T]) extends GenList[T] {
def isEmpty: boolean = false;
def head: T = x;
def tail: GenList[T] = xs
}
Variance Annotations
 Can also have contravariant type parameters
 Useful for an object that can only be written to
 Scala checks that variance annotations are
sound
 covariant positions: immutable field types,
method results
 contravariant: method argument types
 Type system ensures that covariant
parameters are only used covariant positions
(similar for contravariant)
Types as members
abstract class AbsCell {
type T;
val init: T;
private var value: T = init;
def get: T = value;
def set(x: T): unit = { value = x }
}
def createCell : AbsCell {
new AbsCell { type T = int; val init = 1 }
}
 Clients of createCell cannot rely on the fact that
T is int, since this information is hidden from them
Discussion/Critiques
 Scala has nominal subtyping. Is this good?
 Inheritance and subtyping are conflated in
Scala. Shouldn’t they be separated?
 Mixins in MzScheme vs. Scala – MzScheme
allows a class to parameterize its supertype,
while Scala does not
 Type system does not distinguish null
references from non-null references

Introduction to Scala for Data Science Technology

  • 1.
    Traits  Similar tointerfaces in Java  They may have implementations of methods  But can’t contain state  Can be multiply inherited from
  • 2.
    Example of traits traitSimilarity { def isSimilar(x: Any): Boolean; def isNotSimilar(x: Any): Boolean = !isSimilar(x); } class Point(xc: Int, yc: Int) with Similarity { var x: Int = xc; var y: Int = yc; def isSimilar(obj: Any) = obj.isInstanceOf[Point] && obj.asInstanceOf[Point].x == x; }
  • 3.
    Mixin class composition Basic inheritance model is single inheritance  But mixin classes allow more flexibility class Point2D(xc: Int, yc: Int) { val x = xc; val y = yc; // methods for manipulating Point2Ds } class ColoredPoint2D(u: Int, v: Int, c: String) extends Point2D(u, v) { var color = c; def setColor(newCol: String): Unit = color = newCol; }
  • 4.
    Mixin class compositionexample ColoredPoint2D Point2D class Point3D(xc: Int, yc: Int, zc: Int) extends Point2D(xc, yc) { val z = zc; // code for manipulating Point3Ds } Point3D class ColoredPoint3D(xc: Int, yc: Int, zc: Int, col: String) extends Point3D(xc, yc, zc) with ColoredPoint2D(xc, yc, col); ColoredPoint3D ColoredPoint2D
  • 5.
    Mixin class composition Mixin composition adds members explicitly defined in ColoredPoint2D (members that weren’t inherited)  Mixing a class C into another class D is legal only as long as D’s superclass is a subclass of C’s superclass.  i.e., D must inherit at least everything that C inherited  Why?
  • 6.
    Mixin class composition Remember that only members explicitly defined in ColoredPoint2D are mixin inherited  So, if those members refer to definitions that were inherited from Point2D, they had better exist in ColoredPoint3D  They do, since ColoredPoint3D extends Point3D which extends Point2D
  • 7.
    Views  Defines acoercion from one type to another  Similar to conversion operators in C++/C# trait Set { def include(x: int): Set; def contains(x: int): boolean } def view(list: List) : Set = new Set { def include(x: int): Set = x prepend xs; def contains(x: int): boolean = !isEmpty && (list.head == x || list.tail contains x) }
  • 8.
    Views  Views areinserted automatically by the Scala compiler  If e is of type T then a view is applied to e if:  expected type of e is not T (or a supertype)  a member selected from e is not a member of T  Compiler uses only views in scope Suppose xs : List and view above is in scope val s: Set = xs; xs contains x val s: Set = view(xs); view(xs) contains x
  • 9.
    Compound types motivation defcloneAndReset(obj: ?): Cloneable = { val cloned = obj.clone(); obj.reset; cloned } trait Resetable { def reset: Unit; } trait Cloneable { def clone(); }
  • 10.
    Compound types  InJava, the “solution” is: interface CloneableAndResetable extends Cloneable, Resetable  But if the original object did not use the CloneableAndResetable interface, it won’t work  Scala solution: use compound types (also called intersection types) def cloneAndReset(obj: Cloneable with Resetable): Cloneable = { ... }
  • 11.
    Variance annotations class Array[a]{ def get(index: int): a def set(index: int, elem: a): unit; }  Array[String] is not a subtype of Array[Any]  If it were, we could do this: val x = new Array[String](1); val y : Array[Any] = x; y.set(0, new FooBar()); // just stored a FooBar in a String array!
  • 12.
    Variance Annotations  Covarianceis ok with functional data structures trait GenList[+T] { def isEmpty: boolean; def head: T; def tail: GenList[T] } object Empty extends GenList[All] { def isEmpty: boolean = true; def head: All = throw new Error("Empty.head"); def tail: List[All] = throw new Error("Empty.tail"); } class Cons[+T](x: T, xs: GenList[T]) extends GenList[T] { def isEmpty: boolean = false; def head: T = x; def tail: GenList[T] = xs }
  • 13.
    Variance Annotations  Canalso have contravariant type parameters  Useful for an object that can only be written to  Scala checks that variance annotations are sound  covariant positions: immutable field types, method results  contravariant: method argument types  Type system ensures that covariant parameters are only used covariant positions (similar for contravariant)
  • 14.
    Types as members abstractclass AbsCell { type T; val init: T; private var value: T = init; def get: T = value; def set(x: T): unit = { value = x } } def createCell : AbsCell { new AbsCell { type T = int; val init = 1 } }  Clients of createCell cannot rely on the fact that T is int, since this information is hidden from them
  • 15.
    Discussion/Critiques  Scala hasnominal subtyping. Is this good?  Inheritance and subtyping are conflated in Scala. Shouldn’t they be separated?  Mixins in MzScheme vs. Scala – MzScheme allows a class to parameterize its supertype, while Scala does not  Type system does not distinguish null references from non-null references

Editor's Notes

  • #2 Traits can have code, unlike Java interfaces, but can’t have any state associated with them. Scala allows multiple inheritance of traits
  • #8 Note that changes to the result returned by ‘view’ are not reflected in the original function.