an introduction to scala (2014)

52
William Narmontas An introduction to Scala http://scala.contractors/ https://scalawilliam.com/ City of London April 2014

Upload: william-vykintas-narmontas

Post on 13-Jan-2017

109 views

Category:

Data & Analytics


2 download

TRANSCRIPT

Page 1: An Introduction to Scala (2014)

William Narmontas

An introduction to Scala

http://scala.contractors/

https://scalawilliam.com/

City of LondonApril 2014

Page 2: An Introduction to Scala (2014)

What is Scala?

It’s a ..ScalableLanguage

by Typesafe for the Java Virtual Machine.

Page 3: An Introduction to Scala (2014)

Famous QuotesIf I were to pick a language today other than Java, it would be ScalaJames Gosling, “father” of Java

I can honestly say if someone had shown me the Programming Scala book by Martin Odersky, Lex Spoon & Bill Venners back in 2003 I’d probably have never created GroovyJames Strachan, creator of Groovy

No other language on the JVM seems as capable of being a ‘replacement for Java’ as Scala, and the momentum behind Scala is now unquestionableCharles Nutter, co-creator of JRuby

Page 4: An Introduction to Scala (2014)

Who uses Scala?AppleBank of AmericaBarclaysBBCBSkyBCiscoCitigroupCredit SuisseeBayeHarmonyEDFFourSquareGawkerHSBCITVKlout

LinkedInMorgan StanleyNetflixNovellRackspaceSkySonySpringerThe GuardianTom TomTrafiguraTumblrTwitterUBSVMwareXerox

Page 5: An Introduction to Scala (2014)

Topics

1. Benefits for clients, developers

2. Scala language

3. Scala ecosystem

4. Questions

Page 6: An Introduction to Scala (2014)

Scala for clients1. Migration and the JVM

2. Speed of delivery: domain driven design and testing

3. Scalability and the cloud

4. Support and manpower

Page 7: An Introduction to Scala (2014)

Migration and the JVM- Easy to add

- Libraries

- Reusability

- Developer migration

Page 8: An Introduction to Scala (2014)

Domain Driven Design and Testing

- Type safety- Concise and expressive code- Domain Driven Testing- Tests read naturally

Page 9: An Introduction to Scala (2014)

Scalability and Cloud

- Specific tools

- Genericity

- JVM

Page 10: An Introduction to Scala (2014)

Support and manpower- Permanent available- Contractors available (Harvey Nash!)

- Typesafe https://typesafe.com - Underscore http://underscoreconsulting.com - Us! http://scala.contractors

Page 11: An Introduction to Scala (2014)

Mobile payments platformBefore

- Spring-MVC- Hibernate- HttpClient- JAXB- JUnit

After- Spray- ActiveMQ/JMSscala- Spray Client- Native Scala XML - ScalaTest/Gatling

Page 12: An Introduction to Scala (2014)

Scala for developers1. Migration and the JVM

2. Terse code and type-safety

3. Libraries

4. New paradigms

5. Concurrency

Page 13: An Introduction to Scala (2014)

Migration and JVM- Maven plugin

- Scala library dependency

- JDK6+

- Java-like Scala initially

Page 14: An Introduction to Scala (2014)

Terse code and type-safety- Earlier errors

- Faster iterations

- Easier communication

- Easier testing

Page 15: An Introduction to Scala (2014)

Scala languageThe grassroots

Page 16: An Introduction to Scala (2014)

Essentials- Everything is an expression, returns a value

- val = value = cannot be changed

- var = variable = can be changed

- def = method

Page 17: An Introduction to Scala (2014)

Hello Worldobject HelloExample extends App {

def say(what: String, to: String = "World") {

println(s"$what, $to!")

}

say("Hello")

say("Good Evening", "Scala")

}

Hello, World!

Good Evening, Scala!

Page 18: An Introduction to Scala (2014)

Beginner’s fizz buzzdef fizzbuzz(n: Int) =

if ((n % 3 == 0) && (n % 5 == 0)) "fizzbuzz"

else if (n % 3 == 0) "fizz"

else if (n % 5 == 0) "buzz" else s"$n"

: String = 1, 2, fizz, 4, buzz, fizz, 7, 8, fizz, buzz, 11,

fizz, 13, 14, fizzbuzz, 16, 17, fizz, 19, buzz

(1 to 20) map fizzbuzz mkString ", "

Page 19: An Introduction to Scala (2014)

Collections: word count"this is a test of a word count".split(" ").groupBy(identity)

.mapValues(_.size).toList.sortBy(-_._2).mkString("\n")

(a,2)

(test,1)

(this,1)

(count,1)

(is,1)

(word,1)

(of,1)

Page 20: An Introduction to Scala (2014)

Collections: many kindsval list = List(1, 2, 3, 99) list: List[Int] = List(1, 2, 3, 99)

val newerList = list :+ 333 :+ 2 newerList: List[Int] = List(1, 2, 3, 99, 333, 2)

val javaList = new java.util.ArrayList[Int]() { add(2); add(22) } javaList: java.util.ArrayList[Int] = [2, 22]

import scala.collection.JavaConverters._

javaList.asScala.reverse.map{_*2} : scala.collection.mutable.Buffer[Int] =ArrayBuffer(44, 4)

val m = Map("tall"->"height", "short"->"height", "slow"->"speed", "fast"->"speed")

m: scala.collection.immutable.Map[String,String] =Map(tall -> height, short -> height,slow -> speed, fast -> speed)

m.values.toSet : scala.collection.immutable.Set[String] =Set(height, speed)

Page 21: An Introduction to Scala (2014)

Case Classes: very fittingcase class Dog(name: String, age: Int = 0)

val max = Dog("Max", 12) max: Dog = Dog(Max,12)

max.age : Int = 12

Dog("Spot", 5) == Dog("Spot", 5) : Boolean = true

max.copy(age = 13) : Dog = Dog(Max,13)

Page 22: An Introduction to Scala (2014)

Tuples: case classes lighttype NamePrice = (String, Int)

val getStockNamePrice: String => NamePrice = {

case "APPL" => ("Apple", 54179)

}

val (name, price) = getStockNamePrice("APPL")

getStockNamePrice("APPL")._2

val (ticker, name, price) = ("GOOG", "Google", 57829)

val (key, value) = "urn" -> "urn:scalawilliam.com"

val namePrice = getStockNamePrice("APPL")

namePrice.productIterator.foreach(println)

name: String = Apple

price: Int = 54179

: Int = 54179

ticker: String = GOOG

name: String = Google

price: Int = 57829

key: String = urn

value: String =urn:scalawilliam.com

Apple

54179

Page 23: An Introduction to Scala (2014)

Object-Orientedobject Rational extends App {

case class Rational(numerator: Int, denominator: Int=1) extends Ordered[Rational] {

private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b)

private val g = gcd(numerator.abs, denominator.abs)

val numer = numerator / g

val denom = denominator / g

def + (that: Rational) = Rational(numer * that.denom + that.numer * denom, denom * that.denom)

def - (that: Rational) = Rational(numer * that.denom - that.numer * denom, denom * that.denom)

def unary_- = Rational(-numer, denom)

def * (that: Rational) = Rational(numer * that.numer, denom * that.denom)

def / (that: Rational) = Rational(numer * that.denom, denom * that.numer)

def compare(that: Rational) = this.numer * that.denom - that.numer * this.denom

def ==(that: Rational) = that.numer == numer && that.denom == denom

override def toString = if (denom == 1) s"$numer" else s"$numer/$denom"

}

implicit def toRational(num: Int) = Rational(num)

}

Page 24: An Introduction to Scala (2014)

Object-Oriented1 + Rational(2, 3)

-Rational(2, 3) + 1

Rational(2, 3) * Rational(2, 3)

Rational(10) == Rational(20, 2)

val rationals = List[Rational](

1, 2, Rational(2, 3), Rational(10, 7))

1 > Rational(3, 2)

rationals.sorted

rationals.max

: Rational = 5/3

: Rational = 1/3

: Rational = 4/9

: Boolean = true

: Boolean = false

: List[Rational] = List(1, 2, 2/3, 10/7)

: List[Rational] = List(2/3, 1, 10/7, 2)

: Rational = 2

Page 25: An Introduction to Scala (2014)

Functions are first-classval twoToSix = (1 to 5).map{_+1} Vector(2, 3, 4, 5, 6)

val isEven = (_: Int) % 2 == 0 isEven: Int => Boolean = <function1>

def not[T](p: T => Boolean) =

p andThen {!_}

not[T](val p: T => Boolean)

=> T => Boolean

twoToSix.filter(not(isEven)) Vector(3, 5)

twoToSix.filterNot(isEven)

val (even, odd) = nums partition

isEven

even = Vector(2, 4, 6)

odd = Vector(3, 5)

Vector(3, 5)

Page 26: An Introduction to Scala (2014)

case class Dog(name: String, age: Int = 0)

Matching wisely

def describe(what: Any): String = what match {

case Dog("Doge", _) => "Doge very pattern"

case Dog(name, age) if age == 0 => s"Newborn dog $name"

case first :: _ => s"A list starting with $first"

case other => s"Indescribable $other"

}

Page 27: An Introduction to Scala (2014)

Matching wiselydescribe(Dog("Doge"))

describe(Dog("Spot"))

describe(Dog("Spot", 5))

: String = Newborn dog Spot

: String = Indescribable Dog(Spot,5)

: String = Doge very pattern

: String = A list starting with Dog(Max,0)

: String = Indescribable List()

describe(List(Dog("Max")))

describe(List())

Page 28: An Introduction to Scala (2014)

Lazy computationlazy val externalIpAddress = {

println("Getting external IP address...")

scala.io.Source.fromURL("http://whatismyip.akamai.com/").getLines().mkString

}

externalIpAddress: String = <lazy>

val httpsUrl = s"""https://$externalIpAddress"""

Getting external IP address…httpsUrl: String = https://66.249.68.131

val httpUrl = s"""http://$externalIpAddress"""

httpUrl: String = http://66.249.68.131

Page 29: An Introduction to Scala (2014)

Passing control [email protected]

def retry[T](times: Int)(f: => T): Try[T] =

Try(f) match {

case success @ Success(_) => success

case _ if times > 1 => retry(times - 1)(f)

case failure => failure

}

retry: [T](times: Int)(f: => T)scala.util.Try[T]

Page 30: An Introduction to Scala (2014)

Let’s try this again...var counter = 0

retry(times = 5) {

counter = counter + 1

if ( counter == 4 ) {

s"We are reaching this point at the ${counter}th iteration"

} else {

throw new RuntimeException("Badly failed")

}

}

: scala.util.Try[String] = Success(We are reaching this point at 4th iteration)

Page 31: An Introduction to Scala (2014)

Implicits

implicit def toPerson(name: String) = Person(name)

val person: Person = "Dino"

def greet(implicit person: Person) {

println(s"Hello, ${person.name}!")

}

greet("William")

case class Person(name: String)

greet

Hello, William!

Hello, Dino!

Person(Dino)

implicit val implicitPerson = person Person(Dino)

Page 32: An Introduction to Scala (2014)

implicit class addXmlToUrl(url: java.net.URL) {

def loadAsXml = scala.xml.XML.load(url)

}

Implicits: pimp my library

new java.net.URL("http://weather.yahooapis.com/forecastrss?w=2391279").loadAsXml

\\

"forecast" \\ "@text" mkString ", "

Sunny, Partly Cloudy, Partly Cloudy,

Rain/Snow Showers, Partly Cloudy

Page 33: An Introduction to Scala (2014)

Smart for-comprehensionsval staff = Map(

"IT" -> Map("Jonathan" -> 23, "Margaret" -> 26, "Terrence" -> 41),

"HR" -> Map("Amanda" -> 29, "Juliet" -> 21, "Isabelle" -> 33)

)

val people = for {

(department, people) <- staff.toList

(name, age) <- people

} yield new {

override val toString = s"$name ($age) is working in the $department department."

val personAge = age

}

people.sortBy(_.personAge).mkString("\n")

Juliet (21) is working in the HR department.

Jonathan (23) is working in the IT department.

Margaret (26) is working in the IT department.

Amanda (29) is working in the HR department.

Isabelle (33) is working in the HR department.

Terrence (41) is working in the IT department.

Page 34: An Introduction to Scala (2014)

Reactive Futuresval tradeFeeQuote = future { stock.getTradeFee() }

val currentValueQuote = future { stock.getCurrentValue() }

/** Check out once we've made 5% on our investment **/

val trade = for {

tradeFee <- tradeFeeQuote

currentValue <- currentValueQuote

strikeValue = (stock.initialValue + stock.initialTradeFee + tradeFee) + 5.percent

if currentValue > strikeValue

} yield Sell(stock)

trade map Platform.Execute onComplete {

case Success(stockSale) => println(s"Sold the whole stock: $stockSale")

case Failure(e) => println(s"Didn't sell the stock: $e")

}

Page 35: An Introduction to Scala (2014)

Streams

: List[BigInt] = List(0, 1, 1, 2, 3, 5, 8, 13, 21, 34)

fibs: Stream[BigInt] = Stream(0, ?)

val fibs: Stream[BigInt] =

0 #:: 1 #:: fibs.zip(fibs.tail).map { n => n._1 + n._2 }

fibs.take(10).toList

Page 36: An Introduction to Scala (2014)

Language: what wasn’t covered- Traits- Tail recursion- Folds- Partial functions- Type classes- Extractors- Macros- Options

Page 37: An Introduction to Scala (2014)

Scala’s ecosystemThe exciting stuff

Page 38: An Introduction to Scala (2014)

Scala’s ecosystem- Development tools

- Concurrency tools

- ScalaTest

- Web libraries

- Data libraries

Page 39: An Introduction to Scala (2014)

Development- SBT, scala-maven-plugin- IntelliJ, Eclipse, Typesafe Activator- REPL (Scala; SBT; Maven)- Worksheet- Script

Page 40: An Introduction to Scala (2014)

Akka Actors (DSL) throttlecase object Dump

case object Process

def second = new Date().getSeconds

val throttler = actor(new Act {

val numbers = mutable.Queue[Int]()

become {

case Dump =>

println(s"Dump $numbers")

case Process if numbers.nonEmpty =>

println(s"[$second] processing ${numbers.dequeue()}")

case Process =>

println(s"[$second] Awaiting input...")

case toProcess: Int =>

numbers.enqueue(toProcess)

}

context.system.scheduler.schedule(0.seconds, 1.second, self, Process)

})

for { i <- 5 to 8 } throttler ! i

[55] Processing 5[56] Processing 6[57] Processing 7[58] Processing 8[59] Awaiting input…[0] Awaiting input…[1] Awaiting input…[2] Awaiting input...

Page 41: An Introduction to Scala (2014)

Async def seconds=new java.util.Date().getSeconds

val futureGetAge = future {

Thread.sleep(4000)

println(s"Got age at $seconds")

12

}

val futureGetName = future {

Thread.sleep(2000)

println(s"Got name at $seconds")

"Ralf"

}

async{

println(s"at $seconds")

val age=await{futureGetAge}

val name=await{futureGetName}

println(s"at $seconds")

println(s"$name is $age years old")

}

at 31Got name at 33Got age at 35at 35Ralf is 12 years old

Page 42: An Introduction to Scala (2014)

Scalatraclass ScalatraExample extends ScalatraServlet {

get("/hello/:name") {

params("name") match {

case "" => halt(status = 400, body = "No name given")

case name => <p>Hello, <name>{name}</name>!</p>

}

}

}

Page 43: An Introduction to Scala (2014)

Spray Clientcase class DepositFunds(value: Int)

case class AccountBalance(value: Int)

object DepositorJsonProtocol extends DefaultJsonProtocol {

implicit val depositFundsFormat = jsonFormat1(DepositFunds)

implicit val accountBalanceFormat = jsonFormat1(AccountBalance)

}

import DepositorJsonProtocol._

val pipeline: HttpRequest => Future[AccountBalance] = (

addHeader("X-Forwarded-For", "4.1.2.3")

~> addHeader("X-Account-Id", "159192924")

~> addCredentials(OAuth2BearerToken("bd9cad8121bcadfa2313123d"))

~> sendReceive

~> unmarshal[AccountBalance]

)

val response: Future[AccountBalance] =

pipeline(Post("https://api.netpayments.co.uk/deposit", DepositFunds(42)))

Page 44: An Introduction to Scala (2014)

Play!- Typesafe’s web framework

- Async HTTP

- WebSockets

- Good documentation

Page 45: An Introduction to Scala (2014)

ScalaTestimport org.scalatest._

class SampleSpec extends FlatSpec with Matchers {

"An empty set" should "produce NoSuchElementException when head is invoked" in {

intercept[NoSuchElementException] {

Set.empty.head

}

}

"A non-empty set" must "filter as expected" in {

Set('Red, 'Green, 'Blue) filter {_ == 'Red} should contain only 'Red

}

}

Page 46: An Introduction to Scala (2014)

Scala.JS (scala-js-fiddle)http://www.scala-js-fiddle.com/gist/9405209/Oscilloscope.scala

http://www.scala-js-fiddle.com/gist/9131923

Page 47: An Introduction to Scala (2014)

json4sval hoursWinners: Seq[StockWinner] = for {

JArray(stocks) <- parse(json) \\ "stocks"

JObject(stock) <- stocks

JField("ticker", JString(ticker)) <- stock

JField("price an hour ago", JInt(previousPrice)) <- stock

JField("price now", JInt(currentPrice)) <- stock

upPercent = 100 * (currentPrice - previousPrice) / previousPrice

if upPercent > 0

} yield StockWinner(ticker, upPercent.toInt)

hoursWinners.sortWith(_.upPercent > _.upPercent).take(10)

Page 48: An Introduction to Scala (2014)

scala.xml._import scala.xml._

object FindCoders extends App {

val pretty = new PrettyPrinter(60, 2).format(_: Node)

val feed = XML.load(new java.net.URL("http://www.planetscala.com/atom.xml"))

val result = <coders>{(for {

entry <- feed \\ "entry"

if (entry \\ "code").nonEmpty

name <- entry \ "author" \ "name"

} yield <coder>{name.text}</coder>).distinct}</coders>

pretty andThen println apply result

}

// <coders>

// <coder>Eric</coder>

// <coder>Paul Chiusano</coder>

// <coder>Archontophoenix</coder>

// </coders>

Page 49: An Introduction to Scala (2014)

Conclusion- Java is easy to write, hard to read

- Scala is hard to write, easy to read

- Expressive, concise, powerful, scalable

- Code with a smile on your face

Page 50: An Introduction to Scala (2014)

What do I learn next?

- ScalaTest

- Akka

- Scalatra

- Spray

Page 51: An Introduction to Scala (2014)

What do I do next?

- Start using ScalaTest

- Explore the Typesafe Activator

- Read the The Neophyte's Guide to Scala

- Read Matt Stephens’ Design Driven Testing

Page 52: An Introduction to Scala (2014)

Finally

- @ScalaWilliam & LinkedIn “William Narmontas”

- https://scalawilliam.com/

- http://scala.contractors/ - Open to Consulting.

- [email protected]