scala for curious

Post on 15-Apr-2017

314 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

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

top related