Successfully reported this slideshow.

Scala for Java Developers

6

Share

Upcoming SlideShare
Demystifying Shapeless
Demystifying Shapeless
Loading in …3
×
1 of 56
1 of 56

More Related Content

Related Books

Free with a 14 day trial from Scribd

See all

Scala for Java Developers

  1. 1. Scala for Java Developers © 2011 SpringOne 2GX. All rights reserved. Do not distribute without permission.
  2. 2. What is Scala “ a general purpose programming language designed to express common programming patterns in a concise , elegant , and type-safe way. It smoothly integrates features of object-oriented and functional languages, enabling Java and other programmers to be more productive .” http://www.scala-lang.org
  3. 3. Object-oriented <ul><li>Everything is an object </li></ul><ul><ul><li>No “primitives” </li></ul></ul><ul><li>Classes </li></ul><ul><ul><li>Same as Java, but concise </li></ul></ul><ul><li>Traits </li></ul><ul><ul><li>Interfaces done right </li></ul></ul><ul><li>Singletons </li></ul><ul><ul><li>Language-level concept </li></ul></ul>
  4. 4. Statically typed <ul><li>Rich type system (by Java’s standard) </li></ul><ul><ul><li>Higher-kinded types </li></ul></ul><ul><ul><li>Implicit conversions </li></ul></ul><ul><ul><li>Type evidence </li></ul></ul><ul><li>Expressive type system </li></ul><ul><li>Inferred types </li></ul>
  5. 5. Functional Programming <ul><li>Functions as values </li></ul><ul><ul><li>May be </li></ul></ul><ul><ul><ul><li>Saved </li></ul></ul></ul><ul><ul><ul><li>Passed to other functions (higher-order functions) </li></ul></ul></ul><ul><ul><ul><li> No need to write ugly anonymous classes </li></ul></ul></ul><ul><ul><li>Advanced pattern matching </li></ul></ul><ul><ul><li>Expressions return a value </li></ul></ul><ul><ul><ul><li>if/else, try/catch, match, … </li></ul></ul></ul><ul><li>Promotes immutability </li></ul><ul><ul><li>But Scala doesn’t force it </li></ul></ul>
  6. 6. Java Interoperability <ul><li>Compiles to Java byte code </li></ul><ul><ul><li>Jars, wars, … </li></ul></ul><ul><ul><li>No special operational change </li></ul></ul><ul><li>Scala calling Java, Java calling Scala code is fine </li></ul><ul><li>Whole Java eco-system at your service </li></ul><ul><li>You can write apps using Scala and Spring, today </li></ul>
  7. 7. Hello World: Scripting Style $ scala hello-script.scala Hello World No compilation
  8. 8. Hello World: Porting of Java Code $ scalac hello-java.scala $ scala example.Main Hello World ‘ static’ Inferred semicolons
  9. 9. Hello World: Using the App trait $ scalac hello-app.scala $ scala example.Main Hello World
  10. 10. Simple Class class Person val p = new Person Type Inferred Default access: public No curly braces needed (but allowed)
  11. 11. Simple Class class Person val p: Person = new Person Explicit type specification
  12. 12. Class with constructor class Person(firstName: String, lastName: String) val p = new Person( &quot;Ramnivas&quot; , &quot;Laddad&quot; ) println(p.firstName) // Error Primary constructor Fields – accessible in class body
  13. 13. Class with “getters” class Person( val firstName: String, val lastName: String) val p = new Person( &quot;Ramnivas&quot; , &quot;Laddad&quot; ) println(p.firstName) Value (Java ‘final’)
  14. 14. Class with “getters” and “setters” class Person( var firstName: String, var lastName: String) val p = new Person( &quot;Ramnivas&quot; , &quot;Laddad&quot; ) println(p.firstName) p.firstName = &quot;Ramnivas2” Variable (Java non-final)
  15. 15. Extending a class val s = new Student( &quot;Ramnivas&quot; , &quot;Laddad&quot; , 1) println(s.firstName) println(s.grade)
  16. 16. Defining methods class Person( val firstName: String, val lastName: String) { def name = firstName + &quot; &quot; + lastName override def toString = name } val p = new Person( &quot;Ramnivas&quot; , &quot;Laddad&quot; ) println(p.name) // Ramnivas Laddad println(p) // Ramnivas Laddad Not optional
  17. 17. Uniform access principle class Person( val firstName: String, val lastName: String) { val name = firstName + &quot; &quot; + lastName override def toString = name } val p = new Person( &quot;Ramnivas&quot; , &quot;Laddad&quot; ) println(p.name) // Ramnivas Laddad println(p) // Ramnivas Laddad
  18. 18. Names in Scala <ul><li>Class, method, field names can contain non alpha-numeric characters </li></ul><ul><ul><li>:: </li></ul></ul><ul><ul><li>::: </li></ul></ul><ul><ul><li>~> </li></ul></ul><ul><ul><li>f@#: </li></ul></ul><ul><li>Valuable if used judiciously </li></ul><ul><ul><li>DSLs </li></ul></ul>
  19. 19. More about methods and fields <ul><li>Declaring abstract methods and fields </li></ul><ul><ul><li>Just don’t provide definition </li></ul></ul><ul><ul><li>def learn(subject: String) </li></ul></ul><ul><ul><li>val knowledge </li></ul></ul><ul><li>Classes with abstract method must be declared abstract </li></ul><ul><ul><li>Just as in Java </li></ul></ul><ul><li>Methods can be defined inside methods </li></ul><ul><li>Methods may be marked @tailrec to check for tail recursiveness </li></ul>
  20. 20. Finer access control levels <ul><li>Default access level: public </li></ul><ul><li>Protected: protected </li></ul><ul><ul><li>Same as Java </li></ul></ul><ul><li>Private: </li></ul><ul><ul><li>private </li></ul></ul><ul><ul><li>private [ this ] Access only from this instance </li></ul></ul><ul><ul><li>private [package-name] Access from package and its subpackages </li></ul></ul>
  21. 21. Traits: Interfaces done right trait PartyGoer { val age: Int val yearsUntilLegalDrinking = if (age >= 18) 0 else 18-age }
  22. 22. Collections val people = List( &quot;John&quot; , &quot;Jacob&quot; , &quot;Mike&quot; )
  23. 23. Collections val people = Array( &quot;John&quot; , &quot;Jacob&quot; , &quot;Mike&quot; )
  24. 24. Working with collections: for comprehension for (person <- people) { println(person) }
  25. 25. Working with collections: for comprehension for (person <- people if person startsWith &quot;J&quot; ) { println( &quot;&quot;&quot;Lucky one to start name in &quot;J&quot; &quot;&quot;&quot; + person) } // You are lucky one to start name in &quot;J&quot; John // You are lucky one to start name in &quot;J&quot; Jacob
  26. 26. Working with collections: filter val student1 = new Student( &quot;first1&quot; , &quot;last1&quot; , 1) val student2 = new Student( &quot;first2&quot; , &quot;last2&quot; , 1) val student3 = new Student( &quot;first3&quot; , &quot;last3&quot; , 2) val student4 = new Student( &quot;first4&quot; , &quot;last4&quot; , 6) val students = List(student1, student2, student3, student4)
  27. 27. Working with collections: filter val student1 = new Student( &quot;first1&quot; , &quot;last1&quot; , 1) val student2 = new Student( &quot;first2&quot; , &quot;last2&quot; , 1) val student3 = new Student( &quot;first3&quot; , &quot;last3&quot; , 2) val student4 = new Student( &quot;first4&quot; , &quot;last4&quot; , 6) val students = List(student1, student2, student3, student4)
  28. 28. Working with collections: using _ val student1 = new Student( &quot;first1&quot; , &quot;last1&quot; , 1) val student2 = new Student( &quot;first2&quot; , &quot;last2&quot; , 1) val student3 = new Student( &quot;first3&quot; , &quot;last3&quot; , 2) val student4 = new Student( &quot;first4&quot; , &quot;last4&quot; , 6) val students = List(student1, student2, student3, student4)
  29. 29. Working with collections: passing method as function val student1 = new Student( &quot;first1&quot; , &quot;last1&quot; , 1) val student2 = new Student( &quot;first2&quot; , &quot;last2&quot; , 1) val student3 = new Student( &quot;first3&quot; , &quot;last3&quot; , 2) val student4 = new Student( &quot;first4&quot; , &quot;last4&quot; , 6) val students = List(student1, student2, student3, student4)
  30. 30. Working with collections: partition val student1 = new Student( &quot;first1&quot; , &quot;last1&quot; , 1) val student2 = new Student( &quot;first2&quot; , &quot;last2&quot; , 1) val student3 = new Student( &quot;first3&quot; , &quot;last3&quot; , 2) val student4 = new Student( &quot;first4&quot; , &quot;last4&quot; , 6) val students = List(student1, student2, student3, student4) val (elementarySchoolers, middleSchoolers) = students .partition(_.grade < 6) println( elementarySchoolers ) println( middleSchoolers ) //List(first1 last1, first2 last2, first3 last3) //List(first4 last4) Tuple
  31. 31. Working with collections: transforming val student1 = new Student( &quot;first1&quot; , &quot;last1&quot; , 1) val student2 = new Student( &quot;first2&quot; , &quot;last2&quot; , 1) val student3 = new Student( &quot;first3&quot; , &quot;last3&quot; , 2) val student4 = new Student( &quot;first4&quot; , &quot;last4&quot; , 6) val students = List(student1, student2, student3, student4)
  32. 32. Map println(studentSchools(student1)) // Miller
  33. 33. More collections <ul><li>Set </li></ul><ul><li>IndexedSeq </li></ul><ul><li>Vector (good one!) </li></ul><ul><li>Range </li></ul><ul><ul><li>1 to 100 </li></ul></ul><ul><ul><li>1 until 100 </li></ul></ul><ul><ul><li>2 until 100 by 2 </li></ul></ul><ul><li>… </li></ul><ul><li>Mutable versions </li></ul><ul><li>Parallel versions </li></ul>
  34. 34. Putting it together: Quicksort def quicksort[T](input: Traversable[T]) (ordering: Ordering[T]) : Traversable[T] = if (input.isEmpty) { input } else { val (low, high) = input.tail.partition(ordering.lt(_, input.head)) quicksort(low)(ordering) ++ List(input.head) ++ quicksort(high)(ordering) } println(quicksort(List(1, 3, 4, 5, 1))(Ordering.Int))
  35. 35. Putting it together: Quicksort println(quicksort(List(1, 3, 4, 5, 1)))
  36. 36. Pattern matching: Basics val a:Any = &quot;foo&quot; a match { case str: String => println( &quot;A string: &quot; + str) case i: Int => println( &quot;An int: &quot; + i) case _ => println( &quot;Something else&quot; ) }
  37. 37. Pattern matching: with collections val l = List( &quot;a&quot; , &quot;b&quot; , &quot;c&quot; ) l match { case Nil => println( &quot;Empty!&quot; ) case head :: Nil => println( &quot;Only one item &quot; + head) case head :: tail => println( &quot;Item &quot; + head + &quot; followed by &quot; + tail) }
  38. 38. Quicksort with pattern matching def quicksort[T](input: Traversable[T]) ( implicit ordering: Ordering[T]) : Traversable[T] = input match { case head :: tail => val (low, high) = tail.partition(ordering.lt(_, head)) quicksort(low) ++ List(head) ++ quicksort(high) case _ => input } println(quicksort(List(1, 3, 4, 5, 1)))
  39. 39. Destutter using Pattern matching def destutter[A](lst: List[A]): List[A] = lst match { case h1 :: h2 :: tail if (h1 == h2) => destutter(h2 :: tail) case h1 :: h2 :: tail => h1 :: destutter(h2 :: tail) case _ => lst } // destutter(List(1,1,1,1,1,1)) => List(1) // destutter(List(1,1,4,3,3,2)) => List(1,4,3,2) // destutter(List() )=> List()
  40. 40. Case classes <ul><li>Useful in pattern matching </li></ul><ul><ul><li>“ case” </li></ul></ul><ul><li>Offer many useful common methods </li></ul><ul><ul><li>equals() </li></ul></ul><ul><ul><li>hashCode() </li></ul></ul><ul><ul><li>toString </li></ul></ul><ul><ul><li>copy() </li></ul></ul>
  41. 41. Case classes case class Human(name: String) case class SuperHero(name: String, power: String) val characters = List(Human( &quot;Programmer&quot; ), SuperHero( &quot;Customer&quot; , &quot;money&quot; ), SuperHero( &quot;QA&quot; , &quot;testing&quot; ))
  42. 42. Case classes and pattern matching val actions = for (character <- characters) yield character match { case Human(name) => name + &quot; needs to be saved&quot; case SuperHero(name, power) => name + &quot; will save using &quot; + power } actions.foreach(println)
  43. 43. Pattern matching and extracting just enough val actions = for (character <- characters) yield character match { case Human(name) => name + &quot; needs to be saved&quot; case SuperHero(_, power) => &quot;Could be saved using &quot; + power } actions.foreach(println) // Programmer needs to be saved // Could be saved using money // Could be saved using testing
  44. 44. Regular expressions val text = &quot;Ramnivas Laddad&quot; val Name = &quot;&quot;&quot;(+)+(+)&quot;&quot;&quot; .r val person = text match { case Name(first, last) => Some( new Person(first, last)) case _ => None } println(person) // Some(Ramnivas Laddad)
  45. 45. Options val texts = List( &quot;Ramnivas Laddad&quot; , &quot;foo&quot; , &quot;Scott Andrews&quot; ) val peopleOptions = texts.map { _ match { case Name(first, last) => Some( new Person(first, last)) case _ => None } } println(peopleOptions) // List(Some(Ramnivas Laddad), None, Some(Scott Andrews))
  46. 46. Options: flattening val texts = List( &quot;Ramnivas Laddad&quot; , &quot;foo&quot; , &quot;Scott Andrews&quot; ) val peopleOptions = texts.map { _ match { case Name(first, last) => Some( new Person(first, last)) case _ => None } } println(peopleOptions.flatten) // List(Ramnivas Laddad, Scott Andrews)
  47. 47. Options: flatMap val texts = List( &quot;Ramnivas Laddad&quot; , &quot;foo&quot; , &quot;Scott Andrews&quot; ) val people = texts.flatMap { _ match { case Name(first, last) => Some( new Person(first, last)) case _ => None } } println(people) // List(Ramnivas Laddad, Scott Andrews)
  48. 48. Higher order functions def process() : Unit = { retry(5) { ... } } def retry[T](maxRetry: Int)(thunk: => T) = { def retry(thunk: => T, attempt: Int): T = { try { thunk } catch { case ex if (attempt < maxRetry) => retry(thunk, attempt + 1) } } retry(thunk, 0) } Thunk
  49. 49. Caching using Scala <ul><li>def getQuoteGraph(stock: Stock, </li></ul><ul><li>days: Int) : Array[Byte] = { </li></ul><ul><li>cached( &quot;chart&quot; , stock.ticker + &quot;:&quot; + days) { </li></ul><ul><li>... Expensive calculation </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  50. 50. Caching higher-order function <ul><li>abstract class Caching( val cacheManager: CacheManager) { </li></ul><ul><li>def cached[T](region: String, key: Any) </li></ul><ul><li>(thunk: => T): T = { </li></ul><ul><li>val cache = ... </li></ul><ul><li>if (cache.containsKey(key)) { </li></ul><ul><li>cache.get(key).asInstanceOf[T] </li></ul><ul><li>} else { </li></ul><ul><li>val thunkVal: T = thunk </li></ul><ul><li>cache.put(key, thunkVal) </li></ul><ul><li>thunkVal </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  51. 51. Transaction management <ul><li>def findOrder(orderId: Long) : Order = { </li></ul><ul><li>transactional(readOnly= true ) { </li></ul><ul><li>//... </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>def updateOrder(order: Order) { </li></ul><ul><li>transactional() { </li></ul><ul><li>//... </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  52. 52. Transaction management function <ul><li>def transactional[T](propgation: Propagation = Propagation.REQUIRED, </li></ul><ul><li>isolation: Isolation = Isolation.DEFAULT, </li></ul><ul><li>readOnly: Boolean = false , </li></ul><ul><li>timeout: Int =TransactionDefinition.TIMEOUT_DEFAULT, </li></ul><ul><li>rollbackFor: List[Throwable] = List(), </li></ul><ul><li>noRollbackFor: List[Throwable] = List()) </li></ul><ul><li>(thunk: => T) : T </li></ul>
  53. 53. Transaction management implementation <ul><li>abstract class TransactionManagement( val txManager: PlatformTransactionManager) { </li></ul><ul><li>def transactional[T](...)(thunk: => T) : T = { </li></ul><ul><li>val txAttribute = new TransactionAttributeWithRollbackRules(...) </li></ul><ul><li>val status = txManager.getTransaction(txAttribute) </li></ul><ul><li>try { </li></ul><ul><li>val ret = thunk </li></ul><ul><li>txManager.commit(status) </li></ul><ul><li>ret </li></ul><ul><li>} catch { </li></ul><ul><li>case ex => { </li></ul><ul><li>if (txAttribute.rollbackOn(ex)) { </li></ul><ul><li>txManager.rollback(status) </li></ul><ul><li>} else { </li></ul><ul><li>txManager.commit(status) </li></ul><ul><li>} </li></ul><ul><li>throw ex </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>} </li></ul><ul><li>} </li></ul>
  54. 54. There is more… a lot more <ul><li>Methods/functions </li></ul><ul><ul><li>Default parameters </li></ul></ul><ul><ul><li>Named parameters </li></ul></ul><ul><ul><li>Curried parameters </li></ul></ul><ul><ul><li>Partial functions </li></ul></ul><ul><li>Type system </li></ul><ul><ul><li>Higher-kinded types </li></ul></ul><ul><ul><li>Bounded types </li></ul></ul><ul><ul><li>Implicit type conversion </li></ul></ul><ul><ul><li>Type parameter evidence </li></ul></ul><ul><ul><li>Type aliasing </li></ul></ul><ul><li>Lazy values </li></ul><ul><li>Partial imports </li></ul><ul><li>Actors </li></ul><ul><li>Extractors </li></ul><ul><li>Scala ecosystem </li></ul><ul><li>Combinator/parser </li></ul><ul><li>Continuations </li></ul><ul><li>Compiler plugin </li></ul><ul><li>… </li></ul>
  55. 55. Learning Scala <ul><li>Read a Scala book </li></ul><ul><ul><li>Get the whole picture </li></ul></ul><ul><li>May feel complex at first </li></ul><ul><ul><li>Java-style Scala may serve best during initial exploration </li></ul></ul><ul><ul><li>Over time you will appreciate its simplicity </li></ul></ul><ul><li>Learn Haskell first! </li></ul><ul><ul><li>Might help to break from the Java way of thinking </li></ul></ul>Be ready to be humbled
  56. 56. Scala for Java Developers © 2011 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Editor's Notes

  • No access spec (default: public), no parentheses, type inference
  • How constructor params can be used in body
  • ×