3. Java and the JVM
Scala Fundamentals
Java
1995 Scala
2003
Clojure
2007
JRuby
2001
Groovy
2004
Jython
1997
Quercus
1999
JVM
OS
Hardware
4. What is Scala?
Scala Fundamentals
Scala is a programming language for the JVM
• Object oriented paradigm
Objects, inheritance, polymorphism,
overloading…
• Functional paradigm
Immutable state, no side-effects
Application of functions that transform values
• VERY strongly typed
• Interops with Java
5. var variable
• Evaluated once
• Reassignable multiple times
• Avoid it
// explicit type
var age: Int = 36
// implicit type
var isValid = true
// reassignment
isValid = false
isValid = !isValid
// error: type mismatch
isValid = “hello”
Inferred type
: Boolean
Defining things – Variable values
Scala Fundamentals
6. var variable
val value
• Evaluated once
• No reassignable (~ final)
// implicit type
val age = 36
val π = 3.14159
val φ = (1 + math.sqrt(5)) / 2
// explicit type
val age: Int = 36
// error: reassignment to val
age = 42
// error: reassignment to val
age = “hello”
Defining things – Constant values
Scala Fundamentals
7. var variable
val value
lazy val value
• Evaluated once, but only when needed
• No reassignable (~ final)
• Adds small overhead
• There is not a lazy var
// not yet evaluated
lazy val expensiveOp = ackermann(5, 5)
// expensiveOp remains unevaluated
val result =
if (false) expensiveOp
else Int.MaxValue
Defining things – Constant values not evaluated until needed
Scala Fundamentals
8. var variable
val value
lazy val value
def function[(args)]
• Evaluated every time it’s called
• Allows parameters
• A constant, argumentless def ⇆ val
// no args, const, should be a val
def π = 3.14159
// implicit return type
def polar2Cartesian(r: Double, θ: Double) =
(r * math.cos(θ), r * math.sin(θ))
// explicit return type
def area(r: Double): Double =
π * math.pow(r, 2)
val circleA = area(30)
val circleB = area(40)
val circleC = area(30)
Defining things – Functions
Scala Fundamentals
9. var variable
val value
lazy val value
def function[(args)]
type typealias
• Type aliases
type ItemType = Int
type Point = (Double, Double)
type PointList = List[Point]
val points: PointList = ...
Defining things – Types
Scala Fundamentals
10. class MyClass
• Public members by default
• Constructor in declaration
class User(name: String) {
def printInfo() =
println(“Hi, I’m ” + name)
}
val user = new User(“Alfonso”)
user.printInfo() // Hi, I’m Alfonso
Object oriented programming – Class basic definition
Scala Fundamentals
11. class MyClass
• Public members by default
• Constructor in declaration
• Secondary constructors as this methods
class User(name: String, age: Int) {
// secondary constructor
def this(name: String) = this(name, 0)
def this(age: Int) = this(“Anonymous”, age)
def printInfo() =
println(s“$name is $age years old”)
}
val fullUser = new User(“Alfonso”, 36)
val anonUser = new User(23)
Object oriented programming – Class constructors
Scala Fundamentals
12. class MyClass
• Public members by default
• Constructor in declaration
• Secondary constructors as this methods
• Fields declared in primary constructor
// args with a val become fields
class User(val name: String, val age: Int) {
def printInfo() =
println(s“$name is $age years old”)
}
val user = new User(“Alfonso”, 36)
println(user.name) // Alfonso
println(user.age) // 36
Object oriented programming – Class fields
Scala Fundamentals
13. class MyClass
• Public members by default
• Constructor in declaration
• Secondary constructors as this methods
• Fields declared in primary constructor
• Can contain virtually any Scala code
class User(val name: String, val age: Int) {
def printInfo() =
println(s“$name is $age years old”)
if (age >= 18) println(“Adult user created”)
else println(“Child user created”)
}
val adult = new User(“Alfonso”, 36)
// Adult user created
val child = new User(“Teresa”, 12)
// Child user created
Object oriented programming – Class body
Scala Fundamentals
14. class MyClass
• Public members by default
• Constructor in declaration
• Secondary constructors as this methods
• Fields declared in primary constructor
• Can contain virtually any Scala code
• Classes can extend other classes
• Abstract classes are also available
• case class for pattern matching (later)
abstract class Person {
def name: String // abstract
def printInfo() = println(s“Hello $name!”)
}
case class User(val name: String, val age:Int)
extends Person {
}
val user = new User(“Alfonso”, 36)
user.printInfo() // Hello Alfonso!
Object oriented programming – Class inheritance
Scala Fundamentals
15. class MyInteger (value: Int = 0) {
def << (x: Int): Int = value * math.pow(10, x)
}
val i = new MyInteger(20)
i.<<(3) // Java style
i << 3 // Infix operator
Scala has no operators, they are method invocations
5 + 10 * 6 // Infix notation
5.+(10.*(6)) // What is actually used
Object oriented programming – Calling class methods: infix operators
Scala Fundamentals
16. class MyClass
object MyObject
• Syntactic sugar to define singletons
object Database {
def connect = { … }
def fetch = { … }
def close = { … }
}
Database connect
Database fetch
Database close
Object oriented programming – Objects as singletons
Scala Fundamentals
17. class MyClass
object MyObject
• Syntactic sugar to define singletons
• Used alongwithclasses:companionobjects
class User(val name: String)
object User {
def create(name: String) = new User(name)
def apply(name: String) = create(name)
}
val user1 = new User(“Alfonso”)
val user2 = User.create(“Tulio”)
val user3 = User(“Miguel”) // calls apply()
Object oriented programming – Objects as a class’ companion
Scala Fundamentals
18. class MyClass
object MyObject
trait MyTrait
• Like an abstract class allowing multiple
inheritance
• Like an interface with implemented
members
• Mixins
abstract class Human {}
trait Engineer(role: String) {
val role: String = “Engineer”
def doWork: String // abstract
}
class User(val id: Int, val name: String)
extends Human with Engineer {
override val doWork = “Developing...”
}
val user = new User(1, “Alfonso”)
user doWork
Object oriented programming – Traits
Scala Fundamentals
19. class MyClass
object MyObject
trait MyTrait
• Like an abstract class allowing multiple
inheritance
• Like an interface with implemented
members
• Mixins
• Traits can extend from traits and classes
• Multiple inheritance unleashed
trait Engineer(val role: String) {
def doWork: String
}
trait ChickenSexer {
def classifySex(c: Chicken): Boolean
}
class User(id: Int, val name: String)
extends Engineer with ChickenSexer
Object oriented programming – Traits
Scala Fundamentals
22. val age = 36
// age: Int
val point2D = (5, 3)
// point2D: (Int, Int) = (5, 3)
Functional programming – Higher order functions
Scala Fundamentals
23. Functional programming – Higher order functions
Scala Fundamentals
val age = 36
// age: Int
val point2D = (5, 3)
// point2D: (Int, Int) = (5, 3)
def areEqual(a: Int, b: Int): Boolean = a == b
// areEqual: (Int, Int) => Boolean
Function type generalized: (inType1, inType2…) => (outType1, outType2…)
Functions are first class citizens:
Functions accept functions as parameters
Functions can return other functions
25. Functional programming – Higher order functions
Scala Fundamentals
def magic(x: Int, f: Int => Int): Int = f(x)
// (Int, Int => Int) => Int
// another way to do the same:
type Int2Int = Int => Int
def magic(x: Int, f: Int2Int): Int = f(x)
// (Int, Int2Int) => Int
26. Functional programming – Higher order functions
Scala Fundamentals
def magic(x: Int, f: Int => Int): Int = f(x)
// (Int, Int => Int) => Int
def double(i: Int) = i * 2
// Int => Int
magic(5, double)
// double(5)
// 10
27. Functional programming – Anonymous functions
Scala Fundamentals
def double(i: Int) = i * 2
// Int => Int
// explicit parameter types
(i: Int) => i * 2
// Int => Int
// implicit parameter types
i => i * 2
// ? => ?
def concat(a: Int, b: Int) = a * 10 + b
// (Int, Int) => Int
(a: Int, b: Int) => a * 10 + b
// (Int, Int) => Int
(a, b) => a * 10 + b
// (?, ?) => ?
28. Functional programming – Anonymous functions
Scala Fundamentals
def magic(x: Int, f: Int => Int): Int = f(x)
// (Int, Int => Int) => Int
magic(5, (i: Int) => i * 2)
// 10
magic(5, (b: Boolean) => if (b) 1 else 0)
// type mismatch
magic(5, i => i * 2)
// 10
magic(5, i => i)
// 5
29. Functional programming – Anonymous functions
Scala Fundamentals
def double(i: Int): Int = i * 2
// Int => Int
(i: Int) => i * 2
// Int => Int
i => i * 2
// ? => ?
_ * 2
// ? => ?
magic(5, _ * 2)
// 10
def concat(a: Int, b: Int) = a * 10 + b
// (Int, Int) => Int
(a: Int, b: Int) => a * 10 + b
// (Int, Int) => Int
(a, b) => a * 10 + b
// (?, ?) => ?
_ * 10 + _
// (?, ?) => ?
30. Functional programming – Functional thinking
Scala Fundamentals
List<Integer> list = Arrays.asList(2, 7, 9, 8, 10);
List<Integer> evenList = new ArrayList<Integer>();
for (int number: list) {
if (number % 2 == 0) {
evenList.add(number);
}
}
val list = List(2, 7, 9, 8, 10)
def filterEven(list: List[Int]): List[Int] =
if (list.isEmpty) List()
else if (list.head % 2 == 0)
list.head :: filterEven(list.tail)
else filterEven(list.tail)
val eventList = filterEven(list)
31. Functional programming – Functional thinking
Scala Fundamentals
List<Integer> list = Arrays.asList(2, 7, 9, 8, 10);
List<Integer> evenList = new ArrayList<Integer>();
for (int number: list) {
if (number % 2 == 0) {
evenList.add(number);
}
}
val list = List(2, 7, 9, 8, 10)
val evenList = list filter (_ % 2 == 0)
35. Parameterized types – Variance, covariance, contravariance
Scala Fundamentals
Animal
Cat
Zoo [Animal]
Zoo [Cat]
class Zoo[A]
Zoo is invariant
Zoo [Animal]
Zoo [Cat]
class Zoo[+A]
Zoo is covariant
Zoo [Animal]
Zoo [Cat]
class Zoo[-A]
Zoo is contravariant
36. Pattern matching – Switch on steroids
Scala Fundamentals
def whatIs(object: Any): String = {
object match {
case 0 | “” | false => “empty”
case i: Int if i < 0 => “negative”
case i: Int => “integer”
case 5 => “5 value”
case (_: Int, _: Int) => “ints pair”
case (_, _) => “pair”
case _: Double => “double”
case User(“Xavi”, _) => “It’s Xavi!”
case _ => “unknown”
}
}
whatIs(-13) // negative
whatIs(5) // integer
whatIs((“one”, 1)) // pair
whatIs(0) // empty
whatIs(new User(“Xavi”, 32)) // It’s Xavi!
37. Call by value vs. Call by name – Call by value
Scala Fundamentals
Call by value evaluates all arguments before a function call
def choose(cond: Boolean, output: Integer) =
if (cond) output else Int.MaxValue
choose(false, ackermann(5, 5))
→ choose(false, ackermann(4, ackermann(5, 4))
→ choose(false, ackermann(4, ackermann(4, ackermann(5, 3)))
→ choose(false, ackermann(4, ackermann(4, ackermann(4, ackermann(5, 2)))
…
→→ if (false) ackermann_value else Int.MaxValue
→ Int.MaxValue // so ackermann() was not necessary after all
38. Call by value vs. Call by name – Call by name
Scala Fundamentals
Call by name delays the evaluation until it’s needed
def choose(cond: Boolean, output: => Integer) =
if (cond) output
else Int.MaxValue
choose(false, ackermann(5, 5))
→ if (false) ackermann(5, 5)
else Int.MaxValue
→ Int.MaxValue // ackermann was not calculated
It’s a lazy value. Beware if you need side-effects (need to call the function)
39. Partially applied functions – Some arguments provided
Scala Fundamentals
def sum(a: Int, b: Int, c: Int) = a + b + c
val sum5 = sum(5, _: Int, _: Int)
// (Int, Int) => Int
// ≈ def sum5(b: Int, c: Int): Int = 5 + b + c
val sum5Then10 = sum5(10, _: Int)
// Int => Int
// ≈ def sum5Then10(c: Int): Int = 5 + 10 + c
sum(10, 5, 1) // 16
sum5(4, 1) // 10
sum5Then10(-1) // 14
40. Partial functions – Functions not defined for every possible input value
Scala Fundamentals
val isEvenOrOdd: PartialFunction[Int, String] = {
case x if x % 2 == 0 => “even”
case x if x % 2 == 1 => “odd”
}
// ≈ def isEvenOrOdd(x: Int): String = { x match … }
isEvenOrOdd(8) // even
isEvenOrOdd(5) // odd
isEvenOrOdd(-3) // ?
isEvenOrOdd.isDefinedAt(8) // true
isEvenOrOdd.isDefinedAt(5) // true
isEvenOrOdd.isDefinedAt(-3) // false
41. Currying – Arguments groups
Scala Fundamentals
def magic(f: Int => Int, x: Int): Int = f(x)
def magicCurry(f: Int => Int)(x: Int): Int = f(x)
// (Int => Int)(Int) => Int
val doubleFunc = magicCurry(_ * 2) _
// Int => Int
// ≈ def doubleFunc(x: Int): Int = x * 2
magic(_ * 2, 3) // 6
magicCurry(_ * 2)(3) // 6
doubleFunc(3) // 6
42. Implicits – Automatically provided values
Scala Fundamentals
val list = List(5, 2, 9, 6, 0, 1)
implicit def compare(a: Int, b: Int): Int
def sort(l: List[Int])(implicit comparator: (Int, Int) => Int) = ...
sort(list)(compare)
sort(list) // Looks in the scope for an implicit function of type (Int, Int) => Int
43. Java vs. Scala – Conciseness, verbosity
Scala Fundamentals
public class User {
private String name;
private List<Order> orders;
public User() {
orders = new ArrayList<Order>();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Order> getOrders() {
return orders;
}
public void setOrders(List<Order> orders) {
this.orders = orders;
}
}
class User {
var name: String = _
var orders: List[Order] = Nil
}
44. Java vs. Scala
Scala Fundamentals
def ++[B >: A, That](that: TraversableOnce [B])(implicit bf: CanBuildFrom[List [A], B, That]): That
def retry(noTimes: Int)(block: => Future[T]): Future[T] = {
val ns = (1 to noTimes).toList
val attempts: = ns.map(_ => () => block)
val failed = Future.failed(new Exception)
val result = attempts.foldRight(() => failed)
((block, a) => () => { block() fallbackTo { a() } })
result ()
}
45. Java vs. Scala – The not-so-good news
Scala Fundamentals
• Tough learning curve
Classic OOP/Imperative/Procedural-minded programmers
Also, new concepts that are no familiar to many programmers
Multiple right ways to do the same thing
Language infix operators abuse (foo ~-~> bar <=> baz())
• Sloooow compilation
• Not backward compatible (major versions)
• IDE support sucks improving
• JVM legacy issues