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.

Scala for curious

395 views

Published on

  • Be the first to comment

Scala for curious

  1. 1. Scala for curious val you = new Developer[Any] with ScalaKnowledge
  2. 2. What is Scala? Is it hard to get started? First steps
  3. 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. 4. Scala is Functional language Scala is also Object-oriented language Scala is strongly typed language Runs on JVM, compiles to bytecode
  5. 5. In contrast to C++ more you learn Scala, easier it gets. Scala community member
  6. 6. Scala in production yep, it’s used. A lot.
  7. 7. Hello world! object HelloWorld extends App { println(“Hello world!”) }
  8. 8. Basic ideas #1 Mutability is evil #2 Everything returns data #3 Functions are first-class citizens
  9. 9. #1 Mutability is evil - Side effects - Need in defensive copies - Hell in multithreading - Need to manage changing state
  10. 10. #1 Mutability is evil val count = 9000 count = 9001 // won’t compile var count = 100 count = 101 // compile
  11. 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. 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. 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. 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
  15. 15. Scala Basic Types
  16. 16. #1 Basic types are objects #2 Scala defines Unified type system #3 Types inference
  17. 17. 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
  18. 18. 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!?
  19. 19. 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
  20. 20. Data flow and data structures
  21. 21. Borrowed a lot from Java: - if else - for - while - try, catch But they return some values and have advanced syntax
  22. 22. 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”
  23. 23. Scala OOP basics
  24. 24. #1 Better classes #2 Object == Built-in singleton #3 Traits #4 Case classes #5 Multiple inheritance
  25. 25. #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
  26. 26. #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
  27. 27. #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.
  28. 28. #3 Abstract class abstract class Boo { def config() } class Foo extends Boo with Logging { def config() = {} // implemented in child class }
  29. 29. #4 Case classes What is the difference? case class Chair(height: Int, b:Buyer) vs class Chair(val height:Int, val b:Buyer)
  30. 30. 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
  31. 31. Scala pattern matching switch => match
  32. 32. Pattern matching Is used to match on: class or (partial) value of it, or specific condition
  33. 33. Pattern matching Start with simple: val value = 42; val matchResult = value match { case 42 => “matched!” case _ => “not matched:(” } matchResult = ???? It also returns a value!
  34. 34. 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 = ????
  35. 35. 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 = ????
  36. 36. Now imagine how many if () else statements and logical conditions you can save with it?
  37. 37. Functions, lambdas and all the stuff
  38. 38. 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
  39. 39. Use of lambda or how to define a function? (x: Int, y: String) => x * x Define 0 .. * params Do some stuff and return results
  40. 40. 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
  41. 41. 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!
  42. 42. 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
  43. 43. Curried functions def multiply(a:Int)(b:Int): Int = a +b val fn = multiply(2)(2) // returns 4 Useful when we don’t have both values
  44. 44. 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
  45. 45. 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
  46. 46. Scala collections
  47. 47. Idea was taken from Java and re- implemented properly
  48. 48. Idea was taken from Java and re- implemented properly
  49. 49. Similar abstractions with functional nature
  50. 50. Scala Collections:
  51. 51. Scala Collections: Immutable import scala.collection.mutable._ Mutable import scala.collection.immutable._ Prefer immutable, unless you need mutability for performance
  52. 52. Lists, Maps, Sets, Seq, …. - defined functional methods on collections - chain transformations - transformations as functions - Immutable: return new modified list - Mutable: modify existing
  53. 53. 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
  54. 54. 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]
  55. 55. 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
  56. 56. Again Options? WTF?
  57. 57. Monads
  58. 58. Before we start with Options, Try and Futures, let’s remember childhood :)
  59. 59. Monads, wrap some values and add extra features, aka “Superpower” Value might be anything
  60. 60. Simplified, Monads wrap anything with some additional context. It allows to manipulate on that value
  61. 61. Similar concepts: Promises in js, Optional in Java, etc
  62. 62. 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]
  63. 63. In Scala: def map def flatMap def flatten def reduce def reduceLeft def reduceRight def filter def fold
  64. 64. No panic, let’s just use it
  65. 65. Options
  66. 66. You have a value or not: - Option[TypeOfYourValue] - Some(yourValue) - None Replacement of Null in Java, Js, python
  67. 67. You have a value or not: val maybeString: Option[String] = Some(“I’m string”) val maybeString: Option[String] = None val maybeString: Option[String] = someFunction()
  68. 68. Option val maybeString: Option[String] = someFunction() maybeString match { case Some(s) => println(s) case None => prtinln(“No values found :(”) }
  69. 69. 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!
  70. 70. 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 !!!
  71. 71. 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
  72. 72. Try
  73. 73. Try - we maybe we something done Try[TypeOfYourValue] might be: - Success(someValues) - Failure(e: Exception) Replacement of try {} catch {} in Java
  74. 74. 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”) }
  75. 75. Try example val result = Try(parseSomeStuff()) // Failure(ex) result.map(parsedVal => toUpperCase(parsedVal))
  76. 76. 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)) } }
  77. 77. Future
  78. 78. In future you maybe have a value - Future[TypeOfYourValue] - Success(yourValue) - Failure(exception) Replacement of Future in Java
  79. 79. Basic use of Future val futureVal = Future { get(url) } futureVal on Complete { case Success(v) => println(v) case Failure(ex) => log.error(ex) }
  80. 80. Future advanced usage val futureVal = Future { get(url) } futureVal.map(v => { println(v) v } ).recover { case e => log.error(e) }
  81. 81. Options, Futures, Trys, Lists and a lot more follow idea of Monads
  82. 82. So they also supports compositions!
  83. 83. Thanks!
  84. 84. Q & A

×