workshop scala

116
Scala workshop Created by Fredrik Vraalsen ([email protected]) and Alf Kristian Støyle ([email protected]) Adapted Bert Van Vreckem ([email protected])

Upload: bert-van-vreckem

Post on 28-Jan-2015

126 views

Category:

Education


1 download

DESCRIPTION

I used these slides for a Scala workshop that I gave. They are based on these: http://www.scala-lang.org/node/4454. Thanks to Alf Kristian Støyle and Fredrik Vraalsen for sharing!

TRANSCRIPT

Page 1: Workshop Scala

Scala workshop

Created byFredrik Vraalsen ([email protected])

and Alf Kristian Støyle ([email protected])

AdaptedBert Van Vreckem ([email protected])

Page 2: Workshop Scala

If I were to pick a language to use today other than Java, it would be

Scala.

James Gosling

Page 3: Workshop Scala

Scala, it must be stated, is the current heir apparent to the Java throne. No other language

on the JVM seems as capable of being a "replacement for Java" as Scala, and the

momentum behind Scala is now unquestionable.

Charlies Olivier Nutter - JRuby lead

Page 4: Workshop Scala

Though my tip though for the long term replacement of javac is Scala. I'm very impressed with it! I can honestly say if

someone had shown me the Programming in Scala book by by Martin Odersky, Lex

Spoon & Bill Venners back in 2003 I'd probably have never created Groovy.

James Strachen

Page 5: Workshop Scala

public class Person { private int age; private String name;

public Person(int age, String name) { this.age = age; this.name = name; }

public int getAge() { return this.age; }

public void setAge(int age) { this.age = age; }

public String getName() { return this.name; }

public void setName(String name) { this.name = name; }}

class Person(var age: Int, var name: String)

Page 6: Workshop Scala

List<Person> persons = ... List<Person> adults = new LinkedList<Person>(); List<Person> kids = new LinkedList<Person>();for (Person person : persons) { if (person.getAge() < 18) { kids.add(person); } else { adults.add(person); }}

val (kids, adults) = persons.partition(_.age < 18)

Page 7: Workshop Scala

String s = "!em esreveR";System.out.println(s.reverse());

val s = "!em esreveR"println(s.reverse)

=> Reverse me!

Page 8: Workshop Scala

using(new BufferedReader(new FileReader("f.txt"))) { reader => println(reader.readLine())}

BufferedReader reader = null;try { reader = new BufferedReader(new FileReader("f.txt")); System.out.println(reader.readLine());} finally { if (reader != null) { try { reader.close(); } catch (IOException e) { // Exception on close, ignore } }}

Page 9: Workshop Scala

I will never forget these words: "With great power comes great responsibility." This is my gift, my

curse. Who am I? I'm Spider-man.

Page 10: Workshop Scala

val myList = List(1, 2, 3)val res = (10 /: myList)(_+_)

=> ??

Page 11: Workshop Scala

Scala

● Object oriented and functional● Statically typed● Java compatible

● Complies to Java bytecode (and CLR)● Existing libraries/frameworks

● Better Java

Page 12: Workshop Scala

Todays schedule

● Basic syntax● REPL, IDEs and setup● First class functions● Pattern matching● OO and traits● Functional programming● Higher order functions

Page 13: Workshop Scala

Scala basics

Page 14: Workshop Scala

;

Page 15: Workshop Scala

Type definitions

Scala

s: String

i: Int

Java

String s

int i / Integer i

Page 16: Workshop Scala

Variables

Scala:

val s = "Hello World"

var i = 1

private var j = 3

Java:

public final String s = "Hello World";

public int i = 1;

private int j = 3;

Page 17: Workshop Scala

Methods (3)

Scala:

override def toString = ...

Java:

@Overridepublic String toString()

{...}

Page 18: Workshop Scala

Classes and constructors

Scala:

class Person(val name: String)

Java:

public class Person {private final String

name;public Person(String

name) {this.name = name;

}public String getName() {

return name;}

}

Page 19: Workshop Scala

Traits (= Interface + Mixin)

Scala:

trait Shape {def area: Double

}

class Circle extends Object with Shape

Java:

interface Shape {public double area();

}

public class Circle extends Object implements Shape

Page 20: Workshop Scala

No “static” in Scala

Scala:

object PersonUtil { val ageLimit = 18

def countPersons( persons: List[Person]) = ...}

Java:

public class PersonUtil {public static final int

AGE_LIMIT = 18;

public static int countPersons( List<Person> persons) {

...}

}

Page 21: Workshop Scala

While-loops

Scala:

while (true) {

...}

Java:

while (true) {

...}

Page 22: Workshop Scala

Exceptions

Scala:

throw new Exception(“...”)

try {} catch {

case e: IOException => ...

} finally {}

Java:

throw new Exception(“...”)

try {} catch (IOException e) {

...} finally {}

Page 23: Workshop Scala

Varargs

def foo(values: String*){ }

foo("bar", "baz")

val arr = Array("bar", "baz")

foo(arr: _*)

public void foo(String... values){ }

foo("bar", "baz");

String[] arr = new String[]{"bar", "baz"}foo(arr);

Page 24: Workshop Scala

(Almost) everything is an expression

val res = if (foo) x else y

val res = for (i <- 1 to 10) yield i // List(1, ..., 10)

val res = try { x } catch { ...; y } finally { } // x or y

Page 25: Workshop Scala

Generics

Scala:

List[String]

Java:

List<String>

Page 26: Workshop Scala

Tuples

Scala:

val tuple: Tuple2[Int, String] =

(1, “apple”)

val quadruple =

(2, “orange”, 0.5d, false)

Java:

Pair<Integer, String> tuple = new Pair<Integer, String>(1, “apple”)

... yeah right... ;-)

Page 27: Workshop Scala

Packages

Scala:

package mypackage

...

Java:

package mypackage;

...

Page 28: Workshop Scala

Imports

Scala:

import java.util.{List, ArrayList}

import java.io._

import scala.util.Sorting._

import java.sql.{Date => SDate}

Java:

import java.util.List

import java.util.ArrayList

import java.io.*

???

???

Page 29: Workshop Scala

REPL, IDE and setup

Page 30: Workshop Scala

REPL: Read-Eval-Print Loop

● Command line shell for on-the-fly execution of Scala statements

● $ cd ${SCALA_HOME}/bin$ scala● Windows, e.g. C:\Program Files\Scala 2.8.0● Linux, e.g. /opt/scala or /usr/local/scala

Page 31: Workshop Scala

IDE

● They are all !#$&§? compared to what you are used to with Java support● Netbeans (very good) but bad in other areas...● IntelliJ IDEA (pretty good) but slow compilation,

bonus community edition is free (with Scala)● Eclipse (not all that good) but very fast when

working

Page 32: Workshop Scala

Netbeans 6.9.x installation

● Download pluginshttp://sf.net/projects/erlybird/files/nb-scala/6.9v1.1.0/

● In NetBeans "Tools" | "Plugins",

● click on "Downloaded" tab title,

● click on "Add Plugins..." button,

● choose the directory where the Scala plugins are unzipped,

● select all listed *.nbm files, following the instructions.

● Set ${SCALA_HOME} or %SCALA_HOME% environment variable

● Edit ${NETBEANS_HOME}/etc/netbeans.conf

● Add "-J-Dscala.home=/opt/scala" to netbeans_default_options

● More info: http://wiki.netbeans.org/Scala

Page 33: Workshop Scala

Tasks (20 min)

● Run REPL● Windows: %scala_home%/bin/scala● Linux: scala or /opt/scala/bin/scala● Execute a few statements

● Copy & unpack '\\Helium\Public\Cursussen\Navorming Scala\ScalaTraining.zip'● into 'Documenten\NetbeansProjects' (Windows)● Into '/home/student/NetbeansProjects' (Linux)

Page 34: Workshop Scala

Tasks (20 min)

● Run unit test in IDE (JUnit 4)

● Open the 'ScalaTraining' project in NetBeans

● Try to compile and test the project (should work)

● scalaexamples.intro.MyFirstTest

– Create a failing test– Make it run

● Make the two classes scalaexamples/intro/HelloWorld.scala print “Hello world”. What is the difference?

● Remove comments from @Test for the methods in scalaexamples/intro/CreateStuffTest.scala. Make tests pass.

Page 35: Workshop Scala

First class functions

Page 36: Workshop Scala

First class functions

val even = Function[Int, Boolean] { def apply(i: Int) = i % 2 == 0}

val even: (Int => Boolean) = (i: Int) => i % 2 == 0val even = (i: Int) => i % 2 == 0

even.apply(42) // trueeven(13) // false

Page 37: Workshop Scala

First class functions

val numbers = List(1, 2, 3, 4, 5)

numbers.filter(even) // List(2, 4)

numbers.filter((i: Int) => i > 2) // List(3, 4, 5)numbers.filter(i => i > 2) // List(3, 4, 5)numbers.filter(_ > 2) // List(3, 4, 5)

Page 38: Workshop Scala

Collections

numbers.filter(i => i > 2) // List(3, 4, 5)numbers.find(i => i > 2) // Some(3)numbers.exists(i => i > 2) // truenumbers.forall(i => i > 2) // false

numbers.map(i => i * 2) // List(2, 4, 6, 8, 10)

numbers.foldLeft(0) { (a, b) => a + b } // 15

Page 39: Workshop Scala

Closures

val people = List(Person(“Alf”), Person(“Fredrik”))

var name = “Fredrik”val nameFilter = (p: Person) => p.name == name

people.filter(nameFilter) // Person(“Fredrik”)name = “Alf”people.filter(nameFilter) // Person(“Alf”)

Page 40: Workshop Scala

Tasks (30 min)

● Open the 'first-class-functions' project ● Tests in package

scalaexamples.firstclassfunctions● Add @Test to one and one method● Follow instructions in the code● Make the tests pass

Page 41: Workshop Scala

Pattern matching

Page 42: Workshop Scala

myObject match { case 1 => println("First was hit") case 2 => println("Second was Hit") case _ => println("Unknown") }

Page 43: Workshop Scala

myObject match { case i: Int => println("Found an int") case s: String => println("Found a String") case _ => println("Unknown") }

Page 44: Workshop Scala

myObject match { case i: Int => println("Found an int") case s: String => println("Found a String") case other => println("Unknown " + other) }

Page 45: Workshop Scala

myObject match { case i: Int if i == 1 => println("Found an int") case s: String => println("Found a String") case other => println("Unknown " + other) }

Page 46: Workshop Scala

val res = myObject match { case i: Int if i == 1 => "Found an int" case s: String => "Found a String" case other => "Unknown " + other}

Page 47: Workshop Scala

val res = myObject match { case (first, second) => second case (first, second, third) => third}

Page 48: Workshop Scala

val mathedElement = list match { case List(firstElement, lastElement) => lastElement case List(firstElement, _ *) => firstElement case _ => "failed"}

Page 49: Workshop Scala

def length(list: List[_]): Int = list match { case Nil => 0 case head :: tail => 1 + length(tail) }

Page 50: Workshop Scala

def second_or_0(list:List[Int]) = list match { case List(_, x, _*) => x case _ => 0}

public static Integer getSecondOr0(List<Integer> list) { if (list != null && list.size() >= 2) { return list.get(1); } else { return 0; }}

Page 51: Workshop Scala

Case classes

● Class types that can be used in pattern matching

● Generated into your class:● equals● hashCode● toString● getters (and optionally setters)● ++

Page 52: Workshop Scala

abstract class Person(name: String)case class Man(name: String) extends Person(name)case class Woman(name: String, children: List[Person]) extends Person(name)

Page 53: Workshop Scala

p match { case Man(name) => println("Man with name " + name) case Woman(name, children) => println("Woman with name " + name + " and with " + children.size + " children")}

Page 54: Workshop Scala

val regex = """(\d+)(\w+)""".r val myString = ...

val res: String = myString match { case regex(digits, word) => digits case _ => "None" }

Page 55: Workshop Scala

val regex = """(\d+)(\w+)""".r val myString = ...

val res: Option[String] = myString match { case regex(digit, word) => Some(digit) case _ => None }

Page 56: Workshop Scala

The Option type, never again NullPointerException

● Option has two possible values● Some(value)● None

val someOption: Option[String] = Some("value")val noOption: Option[String] = None

Page 57: Workshop Scala

def getValue(s: Any): Option[String]

getValue(object) match { case Some(value) => println(value) case None => println("Nothing") }

val result = getValue(object).getOrElse("Nothing")

Page 58: Workshop Scala

Tasks (30 min)

● Open the 'pattern-matching' project● Tests in package

scalaexamples.patternmatching● Add @Test to one and one method● Follow instructions in the code● Make the tests pass

Page 59: Workshop Scala

Object orientation andtraits

Page 60: Workshop Scala

Annotations – not marker interfaces

@serializable class Person

@SerialVersionUID(1) class Person

@cloneable class Person

@remote class Service

Page 61: Workshop Scala

object

● object is a “singleton” class● Call may look like static method calls in Java● Can inherit from other classes and traits● Can be passed as a reference

object MyObject { def foo = "bar"}

var baz = MyObject.foo val personObject = MyObjectbaz = personObject.foo

Page 62: Workshop Scala

Companion object

● Can read the companion class' private fields ● Has to be in the same source file

class Person(private val age: Int)

object Person { def getPersonAge(p: Person) = p.age}

val personInstance = new Person(30)val age = Person.getPersonAge(personInstance)

Page 63: Workshop Scala

Magical apply

class Person private(val age: Int)

object Person { def apply(age: Int) = new Person(age)}

var personInstance = Person.apply(30) personInstance = Person(30)

Page 64: Workshop Scala

val myList = List(1, 2, 3)val mySet = Set(1, 2, 3)val myMap = Map(1 -> "one", 2 -> "two")

Not built in, clever use of apply

Page 65: Workshop Scala

Constructors

● Always one primary constructor● Parameters are automatically instance variables● Class “body” is the primary constructors content● Auxiliary constructors MUST call or chain to primary

constructor

class MyClass(myString: String, myInt: Int)

val myOtherInt = 10 println("In main body") }

Page 66: Workshop Scala

Auxiliary constructors

class MyClass(myString: String, myInt: Int) {

def this(myString: String) = this(myString, 0) def this() = { this("foo") println("In default constructor") } }

Page 67: Workshop Scala

Inheritance

class MyClass(myString: String)

class MySubClass(myString: String, myInt: Int) extends MyClass(myString) {

println("MyString: '" + myString + "', MyInt: '" + myInt + "'") }

Page 68: Workshop Scala

Inheritance

● Single class inheritance● Multiple trait mixins

Page 69: Workshop Scala

Syntax

class Person extends AnyRef with java.io.Serializable with java.rmi.Remote

class Person extends java.io.Serializable with java.rmi.Remote

Page 70: Workshop Scala

Traits

● “Multiple inheritance done right”● Implement methods● Initialized fields● Abstract methods● Abstract fields● Abstract types● Does not have constructors● Call to super → strict semantics

Page 71: Workshop Scala

scala.Ordered trait

trait Ordered[A] { def compare(that: A): Int

def < (that: A): Boolean = (this compare that) < 0 def > (that: A): Boolean = (this compare that) > 0 def <= (that: A): Boolean = (this compare that) <= 0 def >= (that: A): Boolean = (this compare that) >= 0}

Page 72: Workshop Scala

The Ordered trait

class Person(private val age: Int) extends Ordered[Person] {

def compare(other: Person) = this.age - other.age}

val person1 = new Person(21)val person2 = new Person(31)person1 < person2 // trueperson1 <= person2 // trueperson1 >= person2 // false

Page 73: Workshop Scala

“Dynamic mixins”

class Person(age: Int) { override def toString = "my age is " + age}

trait MyTrait { override def toString = "I am sure " + super.toString}

val person = new Person(30) with MyTraitprintln(person)

=> I am sure my age is 30

Page 74: Workshop Scala

is-a vs has-a

● Inheritance as usual● Easier to implement has-a● Inheritance vs composition

Page 75: Workshop Scala

Tasks (30 min)

● Open 'oo-traits' project● Tests under scalaexamples

● companionobject● inheritance● traits

● Add @Test to one and one method● Follow instructions in code● Make tests pass

Page 76: Workshop Scala

Functional programming

Page 77: Workshop Scala

“Functional programming”

● First class functions● Pattern matching● Higher order functions

Page 78: Workshop Scala

Functional programming

● Purity● Mathematical functions have no side effects

● f(x) = 2x + 3● y = sin(x)

● Mathematical functions always give same result for same input● Only immutable objects (and object graphs)

Page 79: Workshop Scala

In practice

● All fields must be immutable● All methods must return something● No side-effects from method calls

● println("...") is also a side effect!

Page 80: Workshop Scala

List

● head :: tail● Prepends to the head of the list● Other operations (filter, map, remove,

partition...) returns a new List instance

Page 81: Workshop Scala

scala.collection.immutable

● ...or scala.collection.mutable● Pick your poison!

Page 82: Workshop Scala

Scala 2.8

● Case classes get copy methods● Constructors and methods get

● named parametersdef resize(width: Int, height: Int) = { ... }resize(height = 42, width = 120)

● default parametersdef f(elems: List[Int], x: Int = 0, cond: Boolean = true)f(List(1))f(Nil, cond = false)

Page 83: Workshop Scala

Strive to be pure

● Parallelization and concurrency (no synchronization)

● Usually easier to find errors (a lot less state)● Easier to test

Page 84: Workshop Scala

Refactoring imperative style code def printMultiTable() { var i = 1 // row while (i <= 10) { var j = 1 // column while (j <= 10) { val prod = (i * j).toString var k = prod.length // padding while (k < 4) { print(" ") k += 1 } print(prod) j += 1 } println() i += 1 } }

1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50 6 12 18 24 30 36 42 48 54 60 7 14 21 28 35 42 49 56 63 70 8 16 24 32 40 48 56 64 72 80 9 18 27 36 45 54 63 72 81 90 10 20 30 40 50 60 70 80 90 100

Page 85: Workshop Scala

Refactoring imperative style code

● Side effect: printing table● Functional style: return String

● Harder to test● How to test result of println()?

● While loop & vars● Functional style: val, for expressions, helper

functions● Helper functions can be tested separately

Page 86: Workshop Scala

Functional style multiplication table

def makeRowSeq(row: Int) = for (col <- 1 to 10) yield { val prod = (row * col).toString val padding = " " * (4 - prod.length) padding + prod }

def makeRow(row: Int) = makeRowSeq(row).mkString

def multiTable = { val tableSeq = for (row <- 1 to 10) yield makeRow(row) tableSeq.mkString("\n") }

Page 87: Workshop Scala

A closer look at Collections

● Overview of collection traits

http://www.decodified.com/scala/collections-api.xml

Page 88: Workshop Scala

Traversable

● One abstract method:def foreach[U](f: Elem => U)

● 50+ concrete methods● Addition, mapping, conversion, copying, size info,

element retrieval, sub-collection retrieval, subdivision, element tests, folds, string operations, view

http://www.scala-lang.org/docu/files/collections-api/http://www.scala-lang.org/api/

Page 89: Workshop Scala

Iterable

● Abstract method iterator● Default implementation of foreach:

def foreach[U](f:Elem => U): Unit = { val it = iterator while (it.hasNext) f(it.next())}

● Subclasses may override

● Some concrete methods● Subcollections, "zippers", comparison

Page 90: Workshop Scala

Seq, IndexedSeq, LinearSeq

● Sequence: ● iterable that has a length, ● elements have fixed index position, starting with 0

● Operations:● Indexing (apply), search, addition, update, sorting,

reversal, comparison, set operations● IndexedSeq, LinearSeq

● No new operations, but different performance– LinearSeq: efficient head, tail– IndexedSeq: efficient apply, length

Page 91: Workshop Scala

Sets, SortedSet

● Set = iterable that contain no duplicates● Operations for tests, addition, removal, set

operations

● SortedSet● Iterator/foreach visit elements in given ordering● Default implementation: binary tree

Page 92: Workshop Scala

Maps

● Map = collection of pairs of keys and valuese.g. Map("x" -> 24, "y" -> 25, "z" -> 26)● Operations for lookup, addition/update, removal,

subcollections, transformations

Page 93: Workshop Scala

Immutable collections

http://www.decodified.com/scala/collections-api.xml

Page 94: Workshop Scala

Mutable collections

Page 95: Workshop Scala

Higher order functions

Page 96: Workshop Scala

Higher order functions

● Functions which take functions as parameters and/or return functions

Page 97: Workshop Scala

Higher order functions

Short summary of first class functions:val even: (Int => Boolean) = (i: Int) => i % 2 == 0

Same type definition:def test(numbers: List[Int], f: Int => Boolean) = ...

Call:test(List(1, 2, 3), (i: Int) => i % 2 == 0)

Page 98: Workshop Scala

Higher order functions

def test(numbers: List[Int], f: Int => Boolean) = numbers.map(tall => f(tall))

// List[Boolean]

Page 99: Workshop Scala

Higher order functions

Functions with several parameters must list them in parenthesis:

def test(l: List[String], f: (Int, String) => Boolean)

Page 100: Workshop Scala

call-by-value vs. call-by-name

● by-value: expressions are evaluated before being passed to the function

● by-name: expressions evaluated inside function● nice when computationally expensive● possible to create nice APIs

Page 101: Workshop Scala

call-by-value vs. call-by-name

Example: Logging

def thisTakesTime = { println(“Slow computation”) “result”}logger.debug(thisTakesTime())

Page 102: Workshop Scala

call-by-value

def debug(s: String) { println(“debug”) if (logLevel <= DEBUG) println(s)}

// Slow computation

// debug

// result

Page 103: Workshop Scala

call-by-name

def debug(s: => String) { println(“debug”) if (logLevel <= DEBUG) println(s)}

// debug

// Slow computation

// result

Page 104: Workshop Scala

using(new BufferedReader(new FileReader("f.txt"))) { reader => println(reader.readLine())}

BufferedReader reader = null;try { reader = new BufferedReader(new FileReader("f.txt")); System.out.println(reader.readLine());} finally { if (reader != null) { try { reader.close(); } catch (IOException e) { // Exception on close, ignore } }}

Page 105: Workshop Scala

def using[T <: { def close() }, A] (closeable: T) (f: T => A) = { try { f(closeable) } finally { if (closeable != null) { try { closeable.close() } catch { case e: Exception => // Do something clever!? } } }}

Page 106: Workshop Scala

Tasks (30 min)

● Open 'higher-order-functions' project● Tests in scalaexamples.higherorderfunctions● Add @Test to one and one method● Implement missing functions in PersonFilter

and so on.● Follow instructions in code● Make tests pass

Page 107: Workshop Scala

Where to go next?

Page 108: Workshop Scala

Advanced topics

● Type inference● Implicit conversions● Extractors● Annotations● XML● Parallel programming with Actors● Domain Specific Languages (DSLs)● GUI programming with Scala Swing

Page 109: Workshop Scala

Exercises

● Solutions to exercises:http://github.com/javaBin/scala-training-code/zipball/solutions

● 99 Scala Problems:http://aperiodic.net/phil/scala/s-99/

Page 110: Workshop Scala

Bert's Scala bookmarks:http://www.delicious.com/bertvv/scala

Page 111: Workshop Scala

A lot of blogs

http://www.planetscala.com/

Page 112: Workshop Scala

Mailing lists

[email protected]@listes.epfl.ch

[email protected]@[email protected]

[email protected]

http://www.scala-lang.org/node/199

Page 113: Workshop Scala

Several books

+++http://www.scala-lang.org/node/959

Page 114: Workshop Scala

Creative Commons

http://programming-scala.labs.oreilly.com/index.html

Page 115: Workshop Scala

http://www.scala-lang.org/

Page 116: Workshop Scala

Creative Commons Attribution 3.0 Unported

Scala Training Codehttp://github.com/javaBin/scala-training-code

git clone git://github.com/javaBin/scala-training-code

Scala Training Slideshttp://github.com/javaBin/scala-training-slides

git clone git://github.com/javaBin/scala-training-slides.git