Scala Intro

Download Scala Intro

Post on 28-Jan-2015

103 views

Category:

Technology

1 download

Embed Size (px)

DESCRIPTION

Scala Intro training @ Lohika, Odessa, UA. This is a basic Scala Programming Language overview intended to evangelize the language among any-language programmers.

TRANSCRIPT

<ul><li> 1. Scala Intro val you = new Developer[Any] with ScalaKnowledge</li></ul><p> 2. Is Scala really hard?Can I start using it without going mad?Why zombies? 3. Scala History. Scala 2003 AD 4. Pizza GJ generics in Java Funnel Scala 5. Scala is a pure object-oriented language Scala is also a functional language Strongly statically typed Runs on JVM, compiles to bytecode 6. Scala scalable language def factorial(x: BigInt): BigInt = if (x == 0) 1 else x * factorial(x - 1) 7. In contrast with C++, the more you study Scala, the easier it gets. Unknown Scala community member 8. Scala in Productionhttp://www.scala-lang.org/old/node/1658 9. Hello object HelloZombie extends App { println("Hello, " + "Zombie!") } 10. Another Helloobject HelloZombie { def main(args: Array[String]) { println("Hello, " + "Zombie!") } } 11. You do not need CS degree to code in Scala Application Programmers: A1 A3 levels Library Designers: L1 L3 levelsOne can program very productively in Scala on level A1, which one should be able to pick up in a day or so, coming from Java. Mastering A2 will doubtlessly increase programmer productivity. A3 is for expert programmers with more specialized tasks, not everyone needs to get to that level.http://www.scala-lang.org/old/node/8610.html 12. Scala functional basics 13. #1 - Mutability is evil#2 Everyhting returns data#3 Functions are first-class citizens 14. Mutability is evil Mutable objects are complicated to think about Defensive copies Need to be synchronized in multithreaded env Unobvious side effects 15. Mutability is evil val salary = "2000$" salary = "2500$" // does not compilevar salary = "2000$ salary = "2500$ // compiles 16. Everything returns dataval result = if (true) value1 else value2 val result = for (i x * 2 18. in Scala a function value is an object!Scala =&gt; pure OOP &amp; full-blown functional language 19. Sooo many objects aroundBaaaad performance, yeah? 20. http://readwrite.com/2011/06/06/cpp-go-java-scala-performance-benchmark 21. Scala OOP basics 22. #1 - Class #2 - Object = build-in singleton pattern#3 Case class #4 Abstract class vs Trait #5 Multiple inheritance WAT? Diamond problem solved! 23. Class Class is similar to any other languages class notion class MyZombie { private val index: Int = 0 val name: String = "Zombie0" } 24. Class + Constructorclass MyZombie(index: Int, val name: String) { println("me likes brainz!") } 25. ObjectObjects are singletons object LoneZombie { def growl = println("me sooo sad") } 26. Companion Object class CrawlerZombie(name: String) { def crawl() = println("crawling...") } object CrawlerZombie { def apply(name: String) = { println(name + " is here!") new CrawlerZombie(name) } } val zombie = CrawlerZombie("Mig") zombie.crawl() 27. Case Class Case class = class + sugar + compiler hint case class Zombie(index: Int, name : String) 28. Case Class Sugar1. Properties 2. Pattern Matching 3. Companion Object 29. Abstract class vs TraitAbstract class defines structure Trait defines behaviour 30. Abstract Class abstract class Undead(name: String) { def eat() = { println("Om nom nom") digest() } def digest() } class Zombie(name: String) extends Undead(name) { def digest() = { println("grab brainz") } } 31. Trait abstract class Undead(name: String) { def eat() = { println("Om nom nom") digest() } def digest() } trait Growling{ def growl(msg: String) = println(msg) def scream(msg: String) = println(msg + " !!!") } class Zombie(name: String) extends Undead(name) with Growling { def digest() = { growl("grab brainz") } } 32. Scala Basic Types 33. #1 - Scala basic types are objects #2 Scala implement its own types, wraps and extends some Java classes and types#3 Scala operators are method calls 34. Value typeRangeByte8-bit signed two's complement integer (27 to 27 - 1, inclusive)Short16-bit signed two's complement integer (-215 to 215 - 1, inclusive)Int32-bit signed two's complement integer (-231 to 231 - 1, inclusive)Long64-bit signed two's complement integer (-263 to 263 - 1, inclusive)Char16-bit unsigned Unicode character (0 to 216 - 1, inclusive)Stringa sequence of CharsFloat32-bit IEEE 754 single-precision floatDouble64-bit IEEE 754 double-precision floatBooleantrue or false 35. Operators are methodsOperators uses infix notation val sum = 1 + 2// Scala invokes (1).+(2) 36. Class Hierarchy 37. Null ?var zombie: Zombie = null zombie = new Zombie("Alex") 38. Nothing?def throwLocalizedException(key: String): Nothing = { throw LocalizedException(resolveMessage(key)) } 39. Functions vs methods 40. Functions and methods are not the same! 41. 42. FunctionsNo side effects Evaluates only body and parameters Compiles to FunctionN Defined mostly in Objects 43. Functionsobject KillerModule { def kill = (z: Zombie) =&gt; println("Killing " + z.name) } 44. MethodsDefined in classes Works with class scope 45. Methodsclass ZombieTortureMachine(z: Zombie) { def kill() = println("Killing " + z.name) def starve() = println("Starving " + z.name) } 46. Functions are first-class citizensAssign function definitions to variables val doubled = (x:Int) =&gt; x * 2 47. Functions are first-class citizens Pass function as a parameter def traverseTree (callback: (Element) =&gt; Unit) { val element = ??? //Getting tree element callback(element) } 48. Functions are first-class citizensReturn function as a result value def prepareCalculator(x: Int, y: Int): () =&gt; Int = { println("calculating...") () =&gt; x + y } 49. Type Inference 50. You can omit types in declarations! The compiler will infer them for you. Less typing -&gt; less reading -&gt; happier developers 51. Type inference with variablesprivate val index = 0 val name = "Zombie0" private val index: Int = 0 val name: String = "Zombie0" 52. Type inference with functionsScala compiler can not read thoughts def func (a: Int, b: String) = { a + b } // compiles def func1 (a, b) = { a + b } // does not compile 53. Type inferencedef getZombies(severity: Int) = { if (severity &gt; 10) { List() } else { List(Zombie("Mig"), Zombie("Alex")) } } // inferred type = List[Zombie] 54. Lambda Syntaxval doubler = (n: Int) =&gt; n * 2 val yadobler = { n: Int =&gt; n * 2 } 55. Closures 56. Closure is special kind of a function Closure encloses the local lexical context inside the function body Closures can be implemented using Anonymous classes in Java (yuck!) 57. Simple Closureval multiplier = 2 val doubler = (n: Int) =&gt; n * multiplier 58. Closure vs FunctionPure function calculates its result solely in terms of its arguments!Closure can use the outer lexical context for it computations. One may say that it stores references to the outer values. 59. Collections 60. Sugar : Map Initialization Java: Map mappings = new HashMap() {{ put("One", 1); put("Two", 2); put("Three", 3); }};Scala: val mappings = Map( "one" -&gt; 1, "two" -&gt; 2, "three" -&gt; 3 ) 61. Sugar : Filtering Java: List numbers = new ArrayList(){{ add(1); add(2); add(-55); add(-33); add(122); }}; List negativeNumbers = new ArrayList(); for (Integer number : numbers) { if (number &lt; 0) { negativeNumbers.add(number); } }Scala: val numbers = List(1, 2, -55, -33, 122) val negativeNumbers = numbers.filter(_ &lt; 0) 62. Sugar : Classification Java: List numbers = new ArrayList(){{ add(1); add(2); add(-55); add(-33); add(122); }}; List negativeNumbers = new ArrayList(); List positiveNumbers = new ArrayList(); for (Integer number : numbers) { if (number &lt; 0) { negativeNumbers.add(number); } else { positiveNumbers.add(number); } }Scala: val numbers = List(1, 2, -55, -33, 122) val (positiveNumbers, negativeNumbers) = numbers.span(_ &gt; 0) 63. Stuff : Tuples Tuples can be viewed as simple immutable collections. Tuple can contain up to 22 elements of different types. Very useful when you need to return a complex value from the expression 64. Stuff : Tuples val pair = (22, "zombies") val pair = (22 -&gt; "zombies") // the type is Tuple2[Int, String]println(pair._1) println(pair._2) 65. Mutable vs ImmutablePrefer immutable collections by default. Period. Google for details.Scala uses immutable collections by default val map = Map("one" -&gt; 1) //results in scala.collection.immutable.Map[String,Int] 66. Collections practices Map, Set and List are mostly used collections in Scala Use traits companion object calls to create collections when you do not need specific implementation: Map("one" -&gt; 1) // good HashMap("one" -&gt; 1) // not so good new HashMap("one" -&gt; 1) // won't compile :) 67. Collections API example #1 case class User(name: String, password: String) val users = List("admin:nimda", "user1:asddsa", "root:qwerty") val mappedUsers = users.map { user =&gt; val splitted = user.split(":") User(splitted(0), splitted(1)) } // List[User] = List(User(admin,nimda), User(user1,asddsa), User(root,qwerty)) 68. Collections API example #2 val names = List( "Alex,Viktor,Eugeny", "Dmitry,Yegor, Sergey", "Michael,Sergey")val splitted = names.flatMap(_.split(",").toList).distinct // List(Alex, Viktor, Eugeny, Dmitry, Yegor, Michael, Sergey) 69. Loops &amp; For comprehension 70. Loops &amp; For comprehension Scala has a while loop Scala has a do-while loop They are not expressions (the return type is Unit) 71. Loops &amp; For comprehension Because the while loop results in no value, it is often left out of pure functional languages. Such languages have expressions, not loops. Scala includes the while loop nonetheless, because sometimes an imperative solution can be more readable, especially to programmers with a predominantly imperative background. 72. While loop while (brains.size &gt; 0) { zombie eat brains } 73. Do-While loop do { zombie eat brains } while (brains.size &gt; 0) 74. Friendly adviseTry use recursion instead of loops! And dont feed zombies 75. For expression 76. For expression Looks like a for-loop Behaves as a swiss knife 77. For + generatorfor (zombie "X3" } 83. Structure matching case class User(name: String, lastname: String, age: Int) val users = List( User("Alexey", "Migutsky", 25), User("Alexander", "Albul", 27), User("John", "Doe", 99) ) val determined = users.map { case User("Alexey", _, _) =&gt; "L case User("Alexander", _, _) =&gt; "A case _ =&gt; "X3" }.mkString(",") // L,A,X3 84. Structure matching def describe(list: List[Int]) { list match { case first :: second :: third :: tail =&gt; println("First case") case head :: tail =&gt; println("Second case") case Nil =&gt; println("Empty list") } } describe(List(1,2,3)) // First case describe(List(1, 2)) // Second case describe(List()) // Empty list 85. Exception handling try { //something } catch { case e: IllegalArgumentException =&gt; println("Illegal argument") case _ =&gt; println("Unknown exception") } 86. Implicits 87. ImplicitsThe compiler can insert parameters and call conversion methods automatically based on the types used This behavior can be achieved using the implicit modifier 88. #1 - Implicit parameters #2 Implicit type conversion #3 Pimp my Library 89. Implicit parameters case class Context(data: List[String]) implicit val context = Context(List("a", "b", "c")) object SomeService { def printCtx(implicit ctx: Context) = println(ctx.data.mkString(",")) } SomeService.printCtx // a,b,c 90. Implicit type conversion Compiler will use the implicit conversion method automatically! case class User(first: String, last: String) def printUserInfo(user: User) { println("User name is: " + user.first + ", last name is: " + user.last) } implicit def stringToUser(userString: String): User = { val split = userString.split(" ") User(split(0), split(1)) } printUserInfo("Alexander Albul") 91. Pimp My Library case class User(first: String, last: String) implicit class ExtendedString(str: String) { def toUser: User = { val split = str.split(" ") User(split(0), split(1)) } } def printUserInfo(user: User) { println("User name is: " + user.first + ", last name is: " + user.last) } printUserInfo("Alexander Albul".toUser) 92. Moar Sugar! For those who survived 93. Stuff : Object equality Use == to compare anything1 == 1.0 // true List(1,2,3) == List(1,2,3) // true null == List(1,2,3) // false List(1,2) == "string" // false 94. Stuff : Object equality The equality operator == do the following1. Check the left side for null 2. If left side is not null, then call equals method Scala provides a facility for comparing reference equality, as well, under the name eq. However, eq and its opposite, ne, only apply to objects that directly map to Java objects. 95. Stuff : Packages and Imports Scala code resides in the Java platforms global hierarchy of packages. Package definition is at the top of the file. The structure is reflected on file system. package graveyard class Zombie 96. Stuff : Packages and Imports The other way you can place code into packages in Scala is more like C# namespaces (called packaging) Packages can be nested package graveyard { package gravestone { class Zombie } } 97. Stuff : Packages and Imports In Scala, packages and their members can be imported using import clauses. Imported items can then be accessed by a simple name like Zombie , as opposed to requiring a qualified name like graveyard.gravestone.Zombie. // import Zombie import graveyard.gravestone.Zombie // import all undead horde import graveyard._ 98. Stuff : Packages and Imports Imports may appear anywhere Import may refer to objects (singleton or regular) in addition to packages Import let you rename and hide some of the imported members// please don't do this IRL: aliases must be reasonable! import graveyard.gravestone.{Zombie =&gt; RoseBush} def hideUndead(): RoseBush = { import graveyard.gravestone.{Zombie =&gt; OldMan} new OldMan() } 99. Stuff : Identifiers 1. CamelCase 2. Alphanumeric for variables letters + digits 3. Do not use starting $ - it is reserved for compiler variables 4. Do not use _ in names underscore has other usages5. Constants has first uppercase letter math.Pi 100. Stuff : Method callMethod with 0 parameter can be called without () Method with 1 parameter can be called using infix notation new Test().method // method call new Test().function // res1: () =&gt; Unit = new Test() method1 10 // 13 101. Stuff : Method call Use higher-order functions with infix notation, but not with mixed notationList("abcd","zyxwvu").map (_.toUpperCase).filter (_.length &gt; 5) // bad!List("abcd","zyxwvu") map (_.toUpperCase) filter (_.length &gt; 5) // good 102. Stuff : Method callsUse infix notation only with methods without side effects (which do not modify internal class state)List(1,2) mkString "" // ok new CustomDataset() add "some value" // not ok 103. Lazy evaluationAn expression that has a value, but that is not evaluated until it's actually needed (in another words until the value is actually read). 104. Call by-name parameter Lazy evaluated parameter def callByValue(x: Int) = { //parameter get evaluated upon function call println("x1=" + x) println("x2=" +...</p>