The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is...

26
The Scala API

Transcript of The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is...

Page 1: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

The Scala API

Page 2: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

The Scala API

Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average

programmer can master Others say it’s no more difficult than Java

Some things have been added, but a lot has been simplified

Everyone agrees that the Scala API is harder to understand than the Java API This certainly makes Scala seem more difficult than it is You don’t have to understand everything about a method in

order to use it effectively This lecture is an attempt to de-mystify the Scala API

2

Page 3: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Searching

The API is search oriented; every frame has a search field You can click on a letter and search for methods

3

Page 4: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Icons

C indicates a class T indicates a trait O indicates an object O and C together indicate a

class with a companion object

4

Page 5: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Objects

A class is a template for creating objects But if you need only one object of a given type, you can just

create it directly object Instructor { val name = "David Matuszek" }

Scala provides a number of predefined objects, such as Console

object TryIt { def main(args: Array[String]): Unit = { val c = Console c.print("Hello, console!") }}

Hello, console!

5

Page 6: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Classes

A class is a template for creating objects; it may take parameters Classes may be marked as case, abstract, or final

case classes have special features To create an object, you may omit the word new Case classes can be used in pattern matching Case classes have automatically generated toString, hashCode, and equals methods (which use the constructor parameters)

abstract classes cannot be instantiated final classes cannot be subclassed

6

Page 7: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Creating new objects from classes When you define a class, you usually use the word new to create objects of that class

object TryIt { def main(args: Array[String]): Unit = { val t = new Thing(1) }}class Thing(number: Int) { println(s"I'm Thing $number!")}

If you make the class a case class, you don’t need the word new object TryIt {

def main(args: Array[String]): Unit = { val t = Thing(1) }}case class Thing(number: Int) { println(s"I'm Thing $number!")}

Both objects produce this output: I'm Thing 1!

7

Page 8: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Companion objects and classes If a class and an object have the same name and are defined on the same source

file, they are companions Each has access to all the features of the other

object Thing { private var count = 0 def main(args: Array[String]): Unit = { new Thing(1, 2, 3) println(s"That's $count Things!") }}class Thing(val numbers: Int*) { for (n <- numbers) { println(s"I'm Thing $n!") Thing.count += 1 }}

I'm Thing 1!I'm Thing 2!I'm Thing 3!That's 3 Things!

8

Page 9: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Companion objects and static Values and methods in a companion object are similar to static values and methods in Java

The companion object is often a good place to put factory methods

object Thing { def main(args: Array[String]): Unit = { val t = thingMaker(5) println(t) } def thingMaker(n: Int) = new Thing(n)}case class Thing(val number: Int)

Thing(5)

9

Page 10: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

The apply method The apply method of a companion object typically creates an object of the

companion class scala> val nums = List.apply(1, 2, 3, 4, 5)

nums: List[Int] = List(1, 2, 3, 4, 5) scala> val m = Map.apply(1 -> 10, 2 -> 20)

m: scala.collection.immutable.Map[Int,Int] = Map(1 -> 10, 2 -> 20)

The apply method of an object typically indexes into that object scala> m.apply(2)

res10: Int = 20 scala> nums.apply(2)

res9: Int = 3

thing(arg) gets translated into thing.apply(arg) A case class has an apply method; this is why you don’t need new

10

Page 11: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Traits

A trait is like a Java interface, except that it can have concrete as well as abstract methods

Traits can be “mixed in” to classes and objects trait Stretchable { def stretch(s: String) = s.toList.mkString(" ")}object Thing extends Stretchable { def main(args: Array[String]) { val hi = "Hello, World!" println(stretch(hi)) }}

H e l l o , W o r l d !

11

Page 12: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Int is in the scala package It is abstract, so you can’t directly create an Int It is final, so you can’t create a subclass of Int It extends AnyVal, which is the superclass of values

that in Java are “primitives” AnyVal extends Any, which is the “topmost” class AnyRef also extends Any, and is the class that corresponds to

Java’s Object class

12

Page 13: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Operators are methods

Unlike Java, operators are methods This means that they are all in the Scala API

In Scala, a name can be: Composed of letters, digits, and underscores Composed of “punctuation marks,” excluding brackets and periods Composed of letters, digits, and underscores, then an underscore, then

punctuation marks Composed of just about anything (even whitespace) enclosed in backquotes

For example, in the description of Any: final def ==(arg0: Any): Boolean

Test two objects for equality. The expression x == that is equivalent to if (x eq null) that eq null else x.equals(that).

returns true if the receiver object is equivalent to the argument; false otherwise.

13

Page 14: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Parameters and return values scala> class Animal

defined class Animal

scala> class Mammal extends Animaldefined class Mammal

scala> class Dog extends Mammaldefined class Dog

scala> object Tester { | def identity(m: Mammal): Mammal = m | def test = { | val something: Animal = identity(new Dog) | something | } }defined module Tester

scala> Tester.testres2: Animal = Dog@563625d0

14

Page 15: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Function1 Function1 is declared in the Scala API as

trait Function1[-T1, +R] extends AnyRef The –T1 indicates that the parameter may be a supertype (this is contravariance) The +R indicates that the return value may be a subtype (this is covariance) Functions are contravariant in their argument types and co-variant in their return types class Animal

class Dog extends Animalclass Personclass Student extends Person

def owner(f: Dog => Person) { println("ok") }

def dogOwner(d: Dog) = new Person // exactly as expecteddef petOwner(d: Dog) = new Student // return is subtypedef animalOwner(a: Animal) = new Person // arg is supertype

The following calls are all legal, and all print ok: owner(dogOwner) owner(petOwner) owner(animalOwner)

15

Page 16: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Contravariance in parameters

On the previous slide, Dog extends Animal and Student extends Person

We also had the definitions: def owner(f: Dog => Person) { println("ok") }

The argument to this function has type Dog => Person def dogOwner(d: Dog) = new Person This is a function of exactly the type required, so it works def petOwner(d: Dog) = new Student

This is a function Dog => Student, but Student is a subclass of Person, so it works (covariance)

def animalOwner(a: Animal) = new Person This is a function Animal => Person, but Animal is a superclass of Dog Since this function will take any Animal as a parameter, it will work for a Dog (this is contravariance), and we can use it as a parameter to owner

16

Page 17: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Java isn’t type safe class Animal {}

class Mammal extends Animal {}

public class Animals { public static void main(String[] args) { Mammal[] mammals = new Mammal[1]; Animal[] animals = mammals; animals[0] = new Animal(); System.out.println(animals[0]); }}

This compiles without any problem Exception in thread "main"

java.lang.ArrayStoreException: Animalat Animals.main(Animals.java:9)

17

Page 18: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Covariance, contravariance, invariance

Covariance and contravariance are properties of collections A collection of values of type A is covariant if it may be treated as

a collection of values of some supertype of A That is, you can use a subtype of the expected type Lists are covariant because a List[Dog] may be treated as if it were a List[Animal]

class List [+A] extends LinearSeq[A] A collection of values of type A is contravariant if it may be treated

as a collection of values of some subtype of A That is, you can use a supertype of the expected type trait Function1 [-T1, +R] extends AnyRef This trait defines a function that is contravariant in its argument type, and

covariant in its return type

A collection is invariant if it is neither covariant or contravariant18

Page 19: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Again, with pictures

19

Suppose you have a function of type B → C

B → C

And suppose you would like to give the function a value of type A, and get back a value of type D

A → → D

You can do this if A is a subtype of B, and C is a subtype of D

D

A

Page 20: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Again, with pictures

20

Suppose you have a function of type B → C

B → C

And suppose you would like to give the function a value of type A, and get back a value of type D

A → → D

You can do this if A is a subtype of B, and C is a subtype of D

Page 21: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Variance for mutable structures For type safety

Read-only (source) data structures can be covariant Write-only data types (sinks) can be contravariant If a data structure is both readable and writeable (such as arrays in Java), it

should be invariant Java arrays are covariant

Did Java get it wrong? If arrays were invariant, generic operations that do not depend on the type of

object (shuffling an array, comparing two arrays for equality) would not be possible

Generics (parameterized types) make a solution possible, but not without breaking legacy programs

<T> boolean equalArrays (T[] a1, T[] a2); Unlike Java, Scala has had parameterized types from the beginning

Scala does not infer variance types; that’s up to the programmer

21

Page 22: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Multiple parameter lists def foldLeft [B] (z: B)(op: (B, A) ⇒ B): B

A and B are type parameters z is of type B op is a function that takes a B and an A and returns a B scala> List(1, 2, 3).foldLeft(10.0)(_ + _)

res15: Double = 16.0 The parameter lists allow partial application of the function to create another

function scala> val fold10 = (_: List[Int]).foldLeft(10.0)(_

+ _)fold10: List[Int] => Double = <function1>

Here we are supplying an indefinite receiver and an indefinite final argument (underscores)

scala> fold10(List(1, 2, 3))res26: Double = 16.0

22

Page 23: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Least Upper Bound

The notation B >: A states that B is a superclass of A

All the elements of a List must be of the “same type.” The “cons” operator, ::, is defined in List asdef :: (x: A): List[A] Consing a value of type A to a List[A] returns a List[A] But there is an additional definition,def :: [B >: A] (x: B): List[B]

If B is a superclass of A, B >: A, then adding a B to a List[A] will result in a List[B]

23

Page 24: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Sir With-A-Lot

Scala objects are usually built from small pieces Lots of inheritance, lots of “withing” The above are buttons, allowing you to control how much is displayed

Anything, such as List above, that inherits from Seq (sequence) or TraversableLike, will supply the important functions map, flatMap, filter, and probably some folds

24

Page 25: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

Use the source, Luke

Although the documentation is often difficult to understand, the source code often is not

Scala methods tend to be short The high-level constructs often make code easier to read

Just as Java has javadoc for producing professional-looking documentation, Scala has scaladoc

As your code does not have the same constraints as library code, your scaladoc files will probably not be this complicated

25

Page 26: The Scala API. Scala has a reputation of being a difficult language Some people feel that Scala is beyond what the average programmer can master Others.

26

The End