Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

An Introduction to Scala (2014)

359 views

Published on

An introduction to Scala (2014) for its use cases, pros and cons, including ScalaTest, Akka, domain specific languages, simplicity and conciseness.

Published in: Data & Analytics
  • Be the first to comment

  • Be the first to like this

An Introduction to Scala (2014)

  1. 1. William Narmontas An introduction to Scala http://scala.contractors/ https://scalawilliam.com/ City of London April 2014
  2. 2. What is Scala? It’s a .. Scalable Language by Typesafe for the Java Virtual Machine.
  3. 3. Famous Quotes If I were to pick a language today other than Java, it would be Scala James 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 Groovy James 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 unquestionable Charles Nutter, co-creator of JRuby
  4. 4. Who uses Scala? Apple Bank of America Barclays BBC BSkyB Cisco Citigroup Credit Suisse eBay eHarmony EDF FourSquare Gawker HSBC ITV Klout LinkedIn Morgan Stanley Netflix Novell Rackspace Sky Sony Springer The Guardian Tom Tom Trafigura Tumblr Twitter UBS VMware Xerox
  5. 5. Topics 1. Benefits for clients, developers 2. Scala language 3. Scala ecosystem 4. Questions
  6. 6. Scala for clients 1. Migration and the JVM 2. Speed of delivery: domain driven design and testing 3. Scalability and the cloud 4. Support and manpower
  7. 7. Migration and the JVM - Easy to add - Libraries - Reusability - Developer migration
  8. 8. Domain Driven Design and Testing - Type safety - Concise and expressive code - Domain Driven Testing - Tests read naturally
  9. 9. Scalability and Cloud - Specific tools - Genericity - JVM
  10. 10. Support and manpower - Permanent available - Contractors available (Harvey Nash!) - Typesafe https://typesafe.com - Underscore http://underscoreconsulting.com - Us! http://scala.contractors
  11. 11. Mobile payments platform Before - Spring-MVC - Hibernate - HttpClient - JAXB - JUnit After - Spray - ActiveMQ/JMSscala - Spray Client - Native Scala XML - ScalaTest/Gatling
  12. 12. Scala for developers 1. Migration and the JVM 2. Terse code and type-safety 3. Libraries 4. New paradigms 5. Concurrency
  13. 13. Migration and JVM - Maven plugin - Scala library dependency - JDK6+ - Java-like Scala initially
  14. 14. Terse code and type-safety - Earlier errors - Faster iterations - Easier communication - Easier testing
  15. 15. Scala language The grassroots
  16. 16. Essentials - Everything is an expression, returns a value - val = value = cannot be changed - var = variable = can be changed - def = method
  17. 17. Hello World object 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!
  18. 18. Beginner’s fizz buzz def 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 ", "
  19. 19. 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)
  20. 20. Collections: many kinds val 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)
  21. 21. Case Classes: very fitting case 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)
  22. 22. Tuples: case classes light type 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
  23. 23. Object-Oriented object 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) }
  24. 24. Object-Oriented 1 + 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
  25. 25. Functions are first-class val 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)
  26. 26. 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" }
  27. 27. Matching wisely describe(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())
  28. 28. Lazy computation lazy 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
  29. 29. Passing control structures @annotation.tailrec 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]
  30. 30. 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)
  31. 31. 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)
  32. 32. 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
  33. 33. Smart for-comprehensions val 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.
  34. 34. Reactive Futures val 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") }
  35. 35. 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
  36. 36. Language: what wasn’t covered - Traits - Tail recursion - Folds - Partial functions - Type classes - Extractors - Macros - Options
  37. 37. Scala’s ecosystem The exciting stuff
  38. 38. Scala’s ecosystem - Development tools - Concurrency tools - ScalaTest - Web libraries - Data libraries
  39. 39. Development - SBT, scala-maven-plugin - IntelliJ, Eclipse, Typesafe Activator - REPL (Scala; SBT; Maven) - Worksheet - Script
  40. 40. Akka Actors (DSL) throttle case 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...
  41. 41. 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 31 Got name at 33 Got age at 35 at 35 Ralf is 12 years old
  42. 42. Scalatra class 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> } } }
  43. 43. Spray Client case 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)))
  44. 44. Play! - Typesafe’s web framework - Async HTTP - WebSockets - Good documentation
  45. 45. ScalaTest import 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 } }
  46. 46. Scala.JS (scala-js-fiddle) http://www.scala-js-fiddle.com/gist/9405209/Oscilloscope.scala http://www.scala-js-fiddle.com/gist/9131923
  47. 47. json4s val 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)
  48. 48. 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>
  49. 49. 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
  50. 50. What do I learn next? - ScalaTest - Akka - Scalatra - Spray
  51. 51. 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
  52. 52. Finally - @ScalaWilliam & LinkedIn “William Narmontas” - https://scalawilliam.com/ - http://scala.contractors/ - Open to Consulting. - william@scalawilliam.com

×