KEMBAR78
Scala for Java Developers | PPT
Scala for Java Developers © 2011 SpringOne 2GX. All rights reserved. Do not distribute without permission.
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
Object-oriented Everything is an object No “primitives” Classes Same as Java, but concise Traits Interfaces done right Singletons Language-level concept
Statically typed Rich type system (by Java’s standard) Higher-kinded types Implicit conversions Type evidence Expressive type system Inferred types
Functional Programming Functions as values May be  Saved Passed to other functions (higher-order functions)    No need to write ugly anonymous classes Advanced pattern matching Expressions return a value if/else, try/catch, match, … Promotes immutability But Scala doesn’t force it
Java Interoperability Compiles to Java byte code Jars, wars, … No special operational change Scala calling Java, Java calling Scala code is fine Whole Java eco-system at your service You can write apps using Scala and Spring, today
Hello World: Scripting Style $ scala hello-script.scala Hello World No compilation
Hello World: Porting of Java Code $ scalac hello-java.scala $ scala example.Main Hello World ‘ static’ Inferred semicolons
Hello World: Using the App trait $ scalac hello-app.scala $ scala example.Main Hello World
Simple Class class  Person val  p =  new  Person Type Inferred Default access: public No curly braces needed (but allowed)
Simple Class class  Person val  p: Person =  new  Person Explicit type specification
Class with constructor class  Person(firstName: String,  lastName: String) val  p =  new  Person( "Ramnivas" ,  "Laddad" ) println(p.firstName) // Error Primary constructor Fields – accessible in class body
Class with “getters” class  Person( val  firstName: String,  val  lastName: String) val  p =  new  Person( "Ramnivas" ,  "Laddad" ) println(p.firstName) Value  (Java ‘final’)
Class with “getters” and “setters” class  Person( var  firstName: String,  var  lastName: String) val  p =  new  Person( "Ramnivas" ,  "Laddad" ) println(p.firstName) p.firstName =  "Ramnivas2” Variable (Java non-final)
Extending a class val  s =  new  Student( "Ramnivas" ,  "Laddad" , 1) println(s.firstName) println(s.grade)
Defining methods class  Person( val  firstName: String,  val  lastName: String) { def  name = firstName +  " "  + lastName override   def  toString = name  } val  p =  new  Person( "Ramnivas" ,  "Laddad" ) println(p.name)  // Ramnivas Laddad println(p)  // Ramnivas Laddad Not optional
Uniform access principle class  Person( val  firstName: String,  val  lastName: String) { val   name = firstName +  " "  + lastName override   def  toString = name  } val  p =  new  Person( "Ramnivas" ,  "Laddad" ) println(p.name)  // Ramnivas Laddad println(p)  // Ramnivas Laddad
Names in Scala Class, method, field names can contain non alpha-numeric characters ::  ::: ~> f@#: Valuable if used judiciously DSLs
More about methods and fields Declaring abstract methods  and fields Just don’t provide definition def  learn(subject: String) val  knowledge Classes with abstract method must be declared abstract Just as in Java Methods can be defined inside methods Methods may be marked  @tailrec  to check for tail recursiveness
Finer access control levels Default access level: public Protected:  protected Same as Java Private: private   private [ this ]   Access only from this instance  private [package-name]  Access from package and its subpackages
Traits: Interfaces done right trait  PartyGoer { val  age: Int val  yearsUntilLegalDrinking =  if  (age >= 18) 0  else  18-age }
Collections val  people = List( "John" ,  "Jacob" ,  "Mike" )
Collections val  people = Array( "John" ,  "Jacob" ,  "Mike" )
Working with collections: for comprehension for  (person <- people) { println(person) }
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
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)
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)
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)
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)
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
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)
Map println(studentSchools(student1))  // Miller
More collections Set IndexedSeq Vector (good one!) Range 1 to 100  1 until 100 2 until 100 by 2 … Mutable versions Parallel versions
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))
Putting it together: Quicksort println(quicksort(List(1, 3, 4, 5, 1)))
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; ) }
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) }
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)))
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()
Case classes Useful in pattern matching “ case” Offer many useful common methods equals() hashCode() toString copy()
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; ))
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)
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
Regular expressions val  text =  &quot;Ramnivas Laddad&quot;   val  Name =  &quot;&quot;&quot;(\w+)\s+(\w+)&quot;&quot;&quot; .r val  person = text  match  { case  Name(first, last) =>  Some( new  Person(first, last)) case  _ =>  None } println(person)  // Some(Ramnivas Laddad)
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))
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)
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)
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
Caching using Scala  def  getQuoteGraph(stock: Stock,  days: Int) : Array[Byte] = { cached( &quot;chart&quot; , stock.ticker +  &quot;:&quot;  + days) { ... Expensive calculation  } }
Caching higher-order function abstract   class  Caching( val  cacheManager: CacheManager) { def  cached[T](region: String, key: Any) (thunk: => T): T = { val  cache = ... if  (cache.containsKey(key)) { cache.get(key).asInstanceOf[T] }  else  { val  thunkVal: T = thunk cache.put(key, thunkVal) thunkVal } } }
Transaction management def  findOrder(orderId: Long) : Order = { transactional(readOnly= true ) { //... } } def  updateOrder(order: Order) { transactional() { //... } }
Transaction management function def  transactional[T](propgation: Propagation = Propagation.REQUIRED, isolation: Isolation = Isolation.DEFAULT, readOnly: Boolean =  false , timeout: Int =TransactionDefinition.TIMEOUT_DEFAULT, rollbackFor: List[Throwable] = List(), noRollbackFor: List[Throwable] = List()) (thunk: => T) : T
Transaction management implementation abstract   class  TransactionManagement( val  txManager: PlatformTransactionManager) { def  transactional[T](...)(thunk: => T) : T   = { val  txAttribute =  new  TransactionAttributeWithRollbackRules(...) val  status = txManager.getTransaction(txAttribute) try  { val  ret = thunk txManager.commit(status) ret }  catch  { case  ex => { if  (txAttribute.rollbackOn(ex)) { txManager.rollback(status) }  else  { txManager.commit(status) } throw  ex } } } }
There is more… a lot more Methods/functions Default parameters Named parameters Curried parameters Partial functions Type system Higher-kinded types Bounded types Implicit type conversion Type parameter evidence Type aliasing Lazy values Partial imports Actors Extractors Scala ecosystem Combinator/parser Continuations Compiler plugin …
Learning Scala Read a Scala book Get the whole picture May feel complex at first Java-style Scala may serve best during initial exploration Over time you will appreciate its simplicity Learn Haskell first! Might help to break from the Java way of thinking Be ready to be humbled
Scala for Java Developers © 2011 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Scala for Java Developers

  • 1.
    Scala for JavaDevelopers © 2011 SpringOne 2GX. All rights reserved. Do not distribute without permission.
  • 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.
    Object-oriented Everything isan object No “primitives” Classes Same as Java, but concise Traits Interfaces done right Singletons Language-level concept
  • 4.
    Statically typed Richtype system (by Java’s standard) Higher-kinded types Implicit conversions Type evidence Expressive type system Inferred types
  • 5.
    Functional Programming Functionsas values May be Saved Passed to other functions (higher-order functions)  No need to write ugly anonymous classes Advanced pattern matching Expressions return a value if/else, try/catch, match, … Promotes immutability But Scala doesn’t force it
  • 6.
    Java Interoperability Compilesto Java byte code Jars, wars, … No special operational change Scala calling Java, Java calling Scala code is fine Whole Java eco-system at your service You can write apps using Scala and Spring, today
  • 7.
    Hello World: ScriptingStyle $ scala hello-script.scala Hello World No compilation
  • 8.
    Hello World: Portingof Java Code $ scalac hello-java.scala $ scala example.Main Hello World ‘ static’ Inferred semicolons
  • 9.
    Hello World: Usingthe App trait $ scalac hello-app.scala $ scala example.Main Hello World
  • 10.
    Simple Class class Person val p = new Person Type Inferred Default access: public No curly braces needed (but allowed)
  • 11.
    Simple Class class Person val p: Person = new Person Explicit type specification
  • 12.
    Class with constructorclass 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.
    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.
    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.
    Extending a classval s = new Student( &quot;Ramnivas&quot; , &quot;Laddad&quot; , 1) println(s.firstName) println(s.grade)
  • 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.
    Uniform access principleclass 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.
    Names in ScalaClass, method, field names can contain non alpha-numeric characters :: ::: ~> f@#: Valuable if used judiciously DSLs
  • 19.
    More about methodsand fields Declaring abstract methods and fields Just don’t provide definition def learn(subject: String) val knowledge Classes with abstract method must be declared abstract Just as in Java Methods can be defined inside methods Methods may be marked @tailrec to check for tail recursiveness
  • 20.
    Finer access controllevels Default access level: public Protected: protected Same as Java Private: private private [ this ] Access only from this instance private [package-name] Access from package and its subpackages
  • 21.
    Traits: Interfaces doneright trait PartyGoer { val age: Int val yearsUntilLegalDrinking = if (age >= 18) 0 else 18-age }
  • 22.
    Collections val people = List( &quot;John&quot; , &quot;Jacob&quot; , &quot;Mike&quot; )
  • 23.
    Collections val people = Array( &quot;John&quot; , &quot;Jacob&quot; , &quot;Mike&quot; )
  • 24.
    Working with collections:for comprehension for (person <- people) { println(person) }
  • 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.
    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.
    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.
    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.
    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.
    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.
    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.
  • 33.
    More collections SetIndexedSeq Vector (good one!) Range 1 to 100 1 until 100 2 until 100 by 2 … Mutable versions Parallel versions
  • 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.
    Putting it together:Quicksort println(quicksort(List(1, 3, 4, 5, 1)))
  • 36.
    Pattern matching: Basicsval 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.
    Pattern matching: withcollections 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.
    Quicksort with patternmatching 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.
    Destutter using Patternmatching 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.
    Case classes Usefulin pattern matching “ case” Offer many useful common methods equals() hashCode() toString copy()
  • 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.
    Case classes andpattern 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.
    Pattern matching andextracting 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.
    Regular expressions val text = &quot;Ramnivas Laddad&quot; val Name = &quot;&quot;&quot;(\w+)\s+(\w+)&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.
    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.
    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.
    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.
    Higher order functionsdef 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.
    Caching using Scala def getQuoteGraph(stock: Stock, days: Int) : Array[Byte] = { cached( &quot;chart&quot; , stock.ticker + &quot;:&quot; + days) { ... Expensive calculation } }
  • 50.
    Caching higher-order functionabstract class Caching( val cacheManager: CacheManager) { def cached[T](region: String, key: Any) (thunk: => T): T = { val cache = ... if (cache.containsKey(key)) { cache.get(key).asInstanceOf[T] } else { val thunkVal: T = thunk cache.put(key, thunkVal) thunkVal } } }
  • 51.
    Transaction management def findOrder(orderId: Long) : Order = { transactional(readOnly= true ) { //... } } def updateOrder(order: Order) { transactional() { //... } }
  • 52.
    Transaction management functiondef transactional[T](propgation: Propagation = Propagation.REQUIRED, isolation: Isolation = Isolation.DEFAULT, readOnly: Boolean = false , timeout: Int =TransactionDefinition.TIMEOUT_DEFAULT, rollbackFor: List[Throwable] = List(), noRollbackFor: List[Throwable] = List()) (thunk: => T) : T
  • 53.
    Transaction management implementationabstract class TransactionManagement( val txManager: PlatformTransactionManager) { def transactional[T](...)(thunk: => T) : T = { val txAttribute = new TransactionAttributeWithRollbackRules(...) val status = txManager.getTransaction(txAttribute) try { val ret = thunk txManager.commit(status) ret } catch { case ex => { if (txAttribute.rollbackOn(ex)) { txManager.rollback(status) } else { txManager.commit(status) } throw ex } } } }
  • 54.
    There is more…a lot more Methods/functions Default parameters Named parameters Curried parameters Partial functions Type system Higher-kinded types Bounded types Implicit type conversion Type parameter evidence Type aliasing Lazy values Partial imports Actors Extractors Scala ecosystem Combinator/parser Continuations Compiler plugin …
  • 55.
    Learning Scala Reada Scala book Get the whole picture May feel complex at first Java-style Scala may serve best during initial exploration Over time you will appreciate its simplicity Learn Haskell first! Might help to break from the Java way of thinking Be ready to be humbled
  • 56.
    Scala for JavaDevelopers © 2011 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Editor's Notes

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