Upload
tim-dev-tim-zadorozhniy
View
314
Download
0
Embed Size (px)
Citation preview
Scala for curiousval you = new Developer[Any] with ScalaKnowledge
What is Scala?
Is it hard to get started?
First steps
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
Scala is Functional language
Scala is also Object-oriented language
Scala is strongly typed language
Runs on JVM, compiles to bytecode
In contrast to C++ more you learn Scala,easier it gets.
Scala community member
Scala in production
yep, it’s used. A lot.
Hello world!
object HelloWorld extends App { println(“Hello world!”)}
Basic ideas
#1 Mutability is evil
#2 Everything returns data
#3 Functions are first-class citizens
#1 Mutability is evil
- Side effects
- Need in defensive copies
- Hell in multithreading
- Need to manage changing state
#1 Mutability is evil
val count = 9000
count = 9001 // won’t compile
var count = 100
count = 101 // compile
#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)
#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)
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)
#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
Scala Basic Types
#1 Basic types are objects
#2 Scala defines Unified type system
#3 Types inference
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
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!?
Type inference
#1 Type inference reduce code and makes refactoring easier!
#2 Inference is resolved by compilerin the end we will get a defined type
Data flow and data structures
Borrowed a lot from Java: - if else
- for
- while
- try, catch
But they return some values and have
advanced syntax
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”
Scala OOP basics
#1 Better classes
#2 Object == Built-in singleton
#3 Traits
#4 Case classes
#5 Multiple inheritance
#1 Better classesclass 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
#2 Objectsobject 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
#3 Traitstrait 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.
#3 Abstract classabstract class Boo {
def config()
}
class Foo extends Boo with Logging {
def config() = {} // implemented in child class
}
#4 Case classesWhat is the difference?
case class Chair(height: Int, b:Buyer)
vs
class Chair(val height:Int, val b:Buyer)
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
Scala pattern matching
switch => match
Pattern matching
Is used to match on:
class or (partial) value of it, or
specific condition
Pattern matchingStart with simple:
val value = 42;
val matchResult = value match {
case 42 => “matched!”
case _ => “not matched:(”
}
matchResult = ????
It also returns a value!
Pattern matchingcase class Chair(h:Int, color:String)
val myChair = Chair(42, “black”);
val matchResult = value match {
case c: Chair => “matched!”
case _ => “not matched:(”
}
matchResult = ????
Pattern matchingcase 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 = ????
Now imagine how many if () else
statements and logical conditions you can
save with it?
Functions, lambdas and all the
stuff
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
Use of lambda or how to define a function?
(x: Int, y: String) => x * x
Define 0 .. * params Do some stuff and return results
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
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!
Partial Function Applicationdef 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
Curried functionsdef multiply(a:Int)(b:Int): Int = a +b
val fn = multiply(2)(2) // returns 4
Useful when we don’t have both values
Variable params lengthdef 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
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
Scala collections
Idea was taken from Java and re-
implemented properly
Idea was taken from Java and re-
implemented properly
Similar abstractions with functional
nature
Scala Collections:
Scala Collections:
Immutableimport scala.collection.mutable._
Mutableimport scala.collection.immutable._
Prefer immutable, unless you need mutability for performance
Lists, Maps, Sets, Seq, ….- defined functional methods on collections
- chain transformations
- transformations as functions
- Immutable: return new modified list
- Mutable: modify existing
Lists - Let’s define itval 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
Lists - Manipulate on itval 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]
Mapsval 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
Again Options?
WTF?
Monads
Before we start with Options, Try and
Futures,
let’s remember childhood :)
Monads, wrap some values and add extra features,
aka “Superpower”
Value might be anything
Simplified, Monads wrap anything with
some additional context.
It allows to manipulate on that value
Similar concepts:
Promises in js, Optional in Java, etc
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]
In Scala:def map
def flatMap
def flatten
def reduce
def reduceLeft
def reduceRight
def filter
def fold
No panic, let’s just use it
Options
You have a value or not:- Option[TypeOfYourValue]- Some(yourValue)- None
Replacement of Null in Java, Js, python
You have a value or not:val maybeString: Option[String] = Some(“I’m string”)
val maybeString: Option[String] = None
val maybeString: Option[String] = someFunction()
Optionval maybeString: Option[String] = someFunction()
maybeString match {
case Some(s) => println(s)
case None => prtinln(“No values found :(”)
}
Option is a monadcase class Company(name: String)
val maybeString: Option[String] = someFunction()
val maybeCompany: Option[Company] =
maybeString.map(str => Company(name))
Options - is an exoskeleton!
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 !!!
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
Try
Try - we maybe we something done
Try[TypeOfYourValue] might be:
- Success(someValues)
- Failure(e: Exception)
Replacement of try {} catch {} in Java
Try exampleval 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”)
}
Try exampleval result = Try(parseSomeStuff()) // Failure(ex)
result.map(parsedVal => toUpperCase(parsedVal))
Real world exampleimport java.io.InputStream
def inputStreamForURL(url: String): Try[Try[Try[InputStream]]] = {
parseURL(url).map { u =>
Try(u.openConnection()).map(conn => Try(conn.getInputStream))
}
}
Future
In future you maybe have a value- Future[TypeOfYourValue]- Success(yourValue)- Failure(exception)
Replacement of Future in Java
Basic use of Future
val futureVal = Future { get(url) }
futureVal on Complete {
case Success(v) => println(v)
case Failure(ex) => log.error(ex)
}
Future advanced usage
val futureVal = Future { get(url) }
futureVal.map(v => {
println(v)
v
} ).recover { case e => log.error(e) }
Options, Futures, Trys, Lists and a lot
more follow idea of Monads
So they also supports compositions!
Thanks!
Q & A