3. What is Scala?
- Built by Martin Odersky in 2003
- JVM programming language
- Backward compatible with Java
- FP driven with OOP features
- Has awesome community
- Great docs
4. Scala is Functional language
Scala is also Object-oriented language
Scala is strongly typed language
Runs on JVM, compiles to bytecode
5. In contrast to C++ more you learn Scala,
easier it gets.
Scala community member
9. #1 Mutability is evil
- Side effects
- Need in defensive copies
- Hell in multithreading
- Need to manage changing state
10. #1 Mutability is evil
val count = 9000
count = 9001 // won’t compile
var count = 100
count = 101 // compile
11. #2 Everything returns data
- Everything is “evaluated” expressions
- Everything returns values or functions
- Functions are values
- return is not needed (last statement does the job)
12. #2 Everything returns data
val result = if (condition) value1 else value2
lazy val result = for (i <- 1 to 10) yield i
def sin(x: Double) = Math.sin(x)
13. Expressions everywhere:
// evaluates to the value
val result = if (condition) value1 else value2
// evaluates to the value as it was used somewhere
lazy val result = for (i <- 1 to 10) yield i
// evaluates every time we call it
def sin(x: Double) = Math.sin(x)
14. #3 Functions are first-class citizens
Function is a value (object)!
val square = (x: Int) => x * x
And can be called later!
val result = square(5) // returns 25
Function here
16. #1 Basic types are objects
#2 Scala defines Unified type system
#3 Types inference
17.
18.
19. Scala defines it’s own unified type system:
#1 Basic types are objects
#2 Root of the family is Any (as Object in Java)
#3 Alias for types type IntMaker = () => Int
20. Type inference
val sum = 2 + 2 // Infers to Int we don’t need a type!
val str = “a” + “b” // Infers to String as well, compiles!
val problem = if (condition) sum else str // will give us Any !
WAT!?
21. Type inference
#1 Type inference reduce code
and makes refactoring easier!
#2 Inference is resolved by compiler
in the end we will get a defined type
23. Borrowed a lot from Java:
- if else
- for
- while
- try, catch
But they return some values and have
advanced syntax
24. Tuple (Pairs)
A way to bind 2 unrelated results:
val t1 = (42, “dog”)
val t2 = (42, “cat”, List(1,2,3))
can be unwrapped:
val (a,b) = t1 // a = 42, b = “dog”
27. #1 Better classes
class Chair(val color: String) {
println(“I’m chair!”);
private val id: Int = 1
def sit(): Unit = {
println(“Sitting on the chair - ”+ id)
}
Class method
Private field
Public field
28. #2 Objects
object Singleton {
val result = “Test”
def foo(): Int = {}
def boo(): Int = {}
}
Singleton.boo()
It creates class that will have only
one instance.
There are no static fields,
though
29. #3 Traits
trait Logging {
val logger = Logger(this.getClass)
}
class Foo extends Boo with Logging {
logger.info(“WAT!!!?”) defined in
Logging
}
Traits are advanced
interfaces in Java.
They can have
methods
implementation and
non-static values.
30. #3 Abstract class
abstract class Boo {
def config()
}
class Foo extends Boo with Logging {
def config() = {} // implemented in child class
}
31. #4 Case classes
What is the difference?
case class Chair(height: Int, b:Buyer)
vs
class Chair(val height:Int, val b:Buyer)
32. case class is “Sugared” class:
#1 Used to store and match on it’s contents
#2 Designed to work with pattern matching
#3 Have implemented equals() hashCode()
and toString()
#4 Have “companion” object already defined
35. Pattern matching
Start with simple:
val value = 42;
val matchResult = value match {
case 42 => “matched!”
case _ => “not matched:(”
}
matchResult = ????
It also returns a
value!
36. Pattern matching
case class Chair(h:Int, color:String)
val myChair = Chair(42, “black”);
val matchResult = value match {
case c: Chair => “matched!”
case _ => “not matched:(”
}
matchResult = ????
37. Pattern matching
case class Chair(h:Int, color:String)
val myChair = Chair(42, “black”);
val matchResult = value match {
case Chair(_, “black”) => “matched!”
case Chair(33, _) => “not matched:(”
case c => “not matched:(” // default case
}
matchResult = ????
38. Now imagine how many if () else
statements and logical conditions you can
save with it?
40. Functions are good.
Scala defines them as first-class citizen.
You can define them and assign to some
value:
val square = (x: Int) => x * x
41. Use of lambda or how to define a function?
(x: Int, y: String) => x * x
Define 0 .. * params Do some stuff and
return results
42. Functions might be params as well
val foo = (n: Int, fn: (Int) => Int) => fn(n)
val square = (x: Int) => x*x
foo(5, square) // returns 25
Function as a parameter
43. Functions might be params as well
val foo = (n: Int, fn: (Int) => Int) => fn(n)
val square = (x: Int) => x*x
foo(5, square) // returns 25
Function as a parameter
It was Function composition!
44. Partial Function Application
def add(a:Int, b:Int) = a +b
val fn = add(2,_:Int) // returns a function
fn(2) // returns 4!
Useful when we don’t have both values
46. Variable params length
def doubleAll(args:Int *) = args.map { arg => arg *2 }
doubleAll(1,2,3) // returns Seq(1,4,6)
This function would return Seq of results, according to the number of
params
47. Functions and methods
Functions assigned in context of the class -
methods
or
They can be assigned to the defs or values in context of
another function
54. Lists, Maps, Sets, Seq, ….
- defined functional methods on collections
- chain transformations
- transformations as functions
- Immutable: return new modified list
- Mutable: modify existing
55. Lists - Let’s define it
val lists = List() // empty list
val firstList = List(List(1,2),List(1,2,4,4)) // why not?
// alternative way to define list
val anotherList = “a”::”b”::”c”::Nil
56. Lists - Manipulate on it
val list = List(1,2,3)
list.map(x => x*x) // returns List(1,4,9)
// let’s chain some stuff
list.map(x => x*x).filter(x => x > 3) // returns List(4,9)
// let’s chain some stuff
list.map(x => x*2).filter(x => x > 1).find(x => x == 4) // returns Option[Int]
57. Maps
val map = Map()
val map = Map(“key” -> “value”) // “key” -> “value” returns Tuple
val newMap = map += (“anotherKey” -> “value”)
val yetAnotherMap = newMap -= (“anotherKey”) // returns yet another map
val result: Option[String] = newMap.get(“key”)
Returns tuple
65. More formal definition:
// get some value to that context
def unit: (a: A) => M[A]
// transform that value with a function but leave it in the context
def bind[B]: (a => M[B]) => M[B]
70. You have a value or not:
- Option[TypeOfYourValue]
- Some(yourValue)
- None
Replacement of Null in Java, Js, python
71. You have a value or not:
val maybeString: Option[String] = Some(“I’m string”)
val maybeString: Option[String] = None
val maybeString: Option[String] = someFunction()
73. Option is a monad
case class Company(name: String)
val maybeString: Option[String] = someFunction()
val maybeCompany: Option[Company] =
maybeString.map(str => Company(name))
Options - is an exoskeleton!
74. Options composition
val maybeHeight: Option[Int] = findChairHeight()
def findChairName(height: Int): Option[String]
def buildChair(h: Int, name: String): Chair = {....}
maybeHeight.flatMap(height => height -> findChairName(height))
.map {
case (height, name) => buildChair(height, name)
} // returns Option[Chair] in case if all vals were Some !!!
75. Even better composition
val maybeHeight: Option[Int] = findChairHeight()
def findChairName(height: Int): Option[String]
def buildChair(h: Int, name: String): Chair = {....}
val maybeChair = for {
height <- findChairHeight() // we got a chair and it’s Some()
name <- findChairName(height) // we got Some name
chair <- buildChair(height, name) // we can use it to build chair!
} yield chair // collect chair
If any value is None - chain breaks, and we return None
77. Try - we maybe we something done
Try[TypeOfYourValue] might be:
- Success(someValues)
- Failure(e: Exception)
Replacement of try {} catch {} in Java
78. Try example
val result = Try(100/0) // Failure(ex)
result match {
case Success(res) => println(“Math is broken”)
case Failure(ex) => println(“We can’t divide by zero”)
}
79. Try example
val result = Try(parseSomeStuff()) // Failure(ex)
result.map(parsedVal => toUpperCase(parsedVal))
80. Real world example
import java.io.InputStream
def inputStreamForURL(url: String): Try[Try[Try[InputStream]]] = {
parseURL(url).map { u =>
Try(u.openConnection()).map(conn => Try(conn.getInputStream))
}
}