scala for java developers

56
Scala for Java Developers © 2011 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Upload: ramnivasladdad

Post on 10-May-2015

1.886 views

Category:

Technology


0 download

DESCRIPTION

My presentation at SpringOne. The target audience is Java developers who haven't started with Scala yet.

TRANSCRIPT

Page 1: Scala for Java Developers

Scala for Java Developers

© 2011 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Page 2: Scala for Java Developers

What is Scala

2

“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

Page 3: Scala for Java Developers

Object-oriented

• Everything is an object– No “primitives”

• Classes– Same as Java, but concise

• Traits– Interfaces done right

• Singletons– Language-level concept

3

Page 4: Scala for Java Developers

Statically typed

• Rich type system (by Java’s standard)– Higher-kinded types

– Implicit conversions

– Type evidence

• Expressive type system• Inferred types

4

Page 5: Scala for Java Developers

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

5

Page 6: Scala for Java Developers

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

6

Page 7: Scala for Java Developers

Hello World: Scripting Style

$ scala hello-script.scalaHello World$ scala hello-script.scalaHello World

No compilationNo compilation

Page 8: Scala for Java Developers

Hello World: Porting of Java Code

$ scalac hello-java.scala$ scala example.MainHello World

$ scalac hello-java.scala$ scala example.MainHello World

‘static’‘static’

Inferred semicolons

Inferred semicolons

Page 9: Scala for Java Developers

Hello World: Using the App trait

$ scalac hello-app.scala$ scala example.MainHello World

$ scalac hello-app.scala$ scala example.MainHello World

Page 10: Scala for Java Developers

Simple Class

class Personclass Person

val p = new Person val p = new Person

Type Inferred

Type Inferred

Default access: public

Default access: public

No curly braces needed (but allowed)

No curly braces needed (but allowed)

Page 11: Scala for Java Developers

Simple Class

class Personclass Person

val p: Person = new Person val p: Person = new Person

Explicit type specificationExplicit type specification

Page 12: Scala for Java Developers

Class with constructor

class Person(firstName: String, lastName: String)class Person(firstName: String, lastName: String)

val p = new Person("Ramnivas", "Laddad") println(p.firstName) // Error val p = new Person("Ramnivas", "Laddad") println(p.firstName) // Error

Primary constructor

Primary constructor

Fields – accessible in class body

Fields – accessible in class body

Page 13: Scala for Java Developers

Class with “getters”

class Person(val firstName: String, val lastName: String)class Person(val firstName: String, val lastName: String)

val p = new Person("Ramnivas", "Laddad") println(p.firstName) val p = new Person("Ramnivas", "Laddad") println(p.firstName)

Value (Java ‘final’)

Value (Java ‘final’)

Page 14: Scala for Java Developers

Class with “getters” and “setters”

class Person(var firstName: String, var lastName: String)class Person(var firstName: String, var lastName: String)

val p = new Person("Ramnivas", "Laddad")println(p.firstName)p.firstName = "Ramnivas2”

val p = new Person("Ramnivas", "Laddad")println(p.firstName)p.firstName = "Ramnivas2”

Variable (Java non-final)

Variable (Java non-final)

Page 15: Scala for Java Developers

Extending a class

val s = new Student("Ramnivas", "Laddad", 1)println(s.firstName)println(s.grade)

val s = new Student("Ramnivas", "Laddad", 1)println(s.firstName)println(s.grade)

Page 16: Scala for Java Developers

Defining methods

class Person(val firstName: String, val lastName: String) { def name = firstName + " " + lastName

override def toString = name }

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 Laddadprintln(p) // Ramnivas Laddad

val p = new Person("Ramnivas", "Laddad")println(p.name) // Ramnivas Laddadprintln(p) // Ramnivas Laddad

Not optionalNot optional

Page 17: Scala for Java Developers

Uniform access principle

class Person(val firstName: String, val lastName: String) { val name = firstName + " " + lastName

override def toString = name }

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 Laddadprintln(p) // Ramnivas Laddad

val p = new Person("Ramnivas", "Laddad")println(p.name) // Ramnivas Laddadprintln(p) // Ramnivas Laddad

Page 18: Scala for Java Developers

Names in Scala

• Class, method, field names can contain non alpha-numeric characters– ::

– :::

– ~>

– f@#:

• Valuable if used judiciously– DSLs

18

Page 19: Scala for Java Developers

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

19

Page 20: Scala for Java Developers

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

20

Page 21: Scala for Java Developers

Traits: Interfaces done right

21

trait PartyGoer { val age: Int val yearsUntilLegalDrinking = if (age >= 18) 0 else 18-age}

trait PartyGoer { val age: Int val yearsUntilLegalDrinking = if (age >= 18) 0 else 18-age}

Page 22: Scala for Java Developers

Collections

val people = List("John", "Jacob", "Mike")val people = List("John", "Jacob", "Mike")

Page 23: Scala for Java Developers

Collections

val people = Array("John", "Jacob", "Mike")val people = Array("John", "Jacob", "Mike")

Page 24: Scala for Java Developers

Working with collections: for comprehension

24

for (person <- people) { println(person)}

for (person <- people) { println(person)}

Page 25: Scala for Java Developers

Working with collections: for comprehension

25

for (person <- people if person startsWith "J") { println("""Lucky one to start name in "J" """ + person)}

// You are lucky one to start name in "J" John// You are lucky one to start name in "J" Jacob

for (person <- people if person startsWith "J") { println("""Lucky one to start name in "J" """ + person)}

// You are lucky one to start name in "J" John// You are lucky one to start name in "J" Jacob

Page 26: Scala for Java Developers

Working with collections: filter

val student1 = new Student("first1", "last1", 1)val student2 = new Student("first2", "last2", 1)val student3 = new Student("first3", "last3", 2)val student4 = new Student("first4", "last4", 6)val students = List(student1, student2, student3, student4)

val student1 = new Student("first1", "last1", 1)val student2 = new Student("first2", "last2", 1)val student3 = new Student("first3", "last3", 2)val student4 = new Student("first4", "last4", 6)val students = List(student1, student2, student3, student4)

Page 27: Scala for Java Developers

Working with collections: filter

val student1 = new Student("first1", "last1", 1)val student2 = new Student("first2", "last2", 1)val student3 = new Student("first3", "last3", 2)val student4 = new Student("first4", "last4", 6)val students = List(student1, student2, student3, student4)

val student1 = new Student("first1", "last1", 1)val student2 = new Student("first2", "last2", 1)val student3 = new Student("first3", "last3", 2)val student4 = new Student("first4", "last4", 6)val students = List(student1, student2, student3, student4)

Page 28: Scala for Java Developers

Working with collections: using _

val student1 = new Student("first1", "last1", 1)val student2 = new Student("first2", "last2", 1)val student3 = new Student("first3", "last3", 2)val student4 = new Student("first4", "last4", 6)val students = List(student1, student2, student3, student4)

val student1 = new Student("first1", "last1", 1)val student2 = new Student("first2", "last2", 1)val student3 = new Student("first3", "last3", 2)val student4 = new Student("first4", "last4", 6)val students = List(student1, student2, student3, student4)

Page 29: Scala for Java Developers

Working with collections: passing method as function

val student1 = new Student("first1", "last1", 1)val student2 = new Student("first2", "last2", 1)val student3 = new Student("first3", "last3", 2)val student4 = new Student("first4", "last4", 6)val students = List(student1, student2, student3, student4)

val student1 = new Student("first1", "last1", 1)val student2 = new Student("first2", "last2", 1)val student3 = new Student("first3", "last3", 2)val student4 = new Student("first4", "last4", 6)val students = List(student1, student2, student3, student4)

Page 30: Scala for Java Developers

Working with collections: partition

val student1 = new Student("first1", "last1", 1)val student2 = new Student("first2", "last2", 1)val student3 = new Student("first3", "last3", 2)val student4 = new Student("first4", "last4", 6)val students = List(student1, student2, student3, student4)

val student1 = new Student("first1", "last1", 1)val student2 = new Student("first2", "last2", 1)val student3 = new Student("first3", "last3", 2)val student4 = new Student("first4", "last4", 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)

val (elementarySchoolers, middleSchoolers) = students.partition(_.grade < 6)println(elementarySchoolers)println(middleSchoolers)//List(first1 last1, first2 last2, first3 last3)//List(first4 last4)

TupleTuple

Page 31: Scala for Java Developers

Working with collections: transforming

val student1 = new Student("first1", "last1", 1)val student2 = new Student("first2", "last2", 1)val student3 = new Student("first3", "last3", 2)val student4 = new Student("first4", "last4", 6)val students = List(student1, student2, student3, student4)

val student1 = new Student("first1", "last1", 1)val student2 = new Student("first2", "last2", 1)val student3 = new Student("first3", "last3", 2)val student4 = new Student("first4", "last4", 6)val students = List(student1, student2, student3, student4)

Page 32: Scala for Java Developers

Map

println(studentSchools(student1)) // Millerprintln(studentSchools(student1)) // Miller

Page 33: Scala for Java Developers

More collections

• Set• IndexedSeq• Vector (good one!)• Range

– 1 to 100 – 1 until 100– 2 until 100 by 2

• …

• Mutable versions• Parallel versions

33

Page 34: Scala for Java Developers

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) }

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))println(quicksort(List(1, 3, 4, 5, 1))(Ordering.Int))

Page 35: Scala for Java Developers

Putting it together: Quicksort

println(quicksort(List(1, 3, 4, 5, 1)))println(quicksort(List(1, 3, 4, 5, 1)))

Page 36: Scala for Java Developers

Pattern matching: Basics

val a:Any = "foo" a match { case str: String => println("A string: " + str) case i: Int => println("An int: " + i) case _ => println("Something else")}

val a:Any = "foo" a match { case str: String => println("A string: " + str) case i: Int => println("An int: " + i) case _ => println("Something else")}

Page 37: Scala for Java Developers

Pattern matching: with collections

val l = List("a", "b", "c") l match { case Nil => println("Empty!") case head :: Nil => println("Only one item " + head) case head :: tail => println("Item " + head + " followed by " + tail) }

val l = List("a", "b", "c") l match { case Nil => println("Empty!") case head :: Nil => println("Only one item " + head) case head :: tail => println("Item " + head + " followed by " + tail) }

Page 38: Scala for Java Developers

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 }

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)))println(quicksort(List(1, 3, 4, 5, 1)))

Page 39: Scala for Java Developers

Destutter using Pattern matching

39

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}

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()

// 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()

Page 40: Scala for Java Developers

Case classes

• Useful in pattern matching– “case”

• Offer many useful common methods– equals()

– hashCode()

– toString

– copy()

40

Page 41: Scala for Java Developers

Case classes

41

case class Human(name: String)case class SuperHero(name: String, power: String)case class Human(name: String)case class SuperHero(name: String, power: String)

val characters = List(Human("Programmer"), SuperHero("Customer", "money"), SuperHero("QA", "testing"))

val characters = List(Human("Programmer"), SuperHero("Customer", "money"), SuperHero("QA", "testing"))

Page 42: Scala for Java Developers

Case classes and pattern matching

42

val actions = for (character <- characters) yield character match { case Human(name) => name + " needs to be saved" case SuperHero(name, power) => name + " will save using " + power }

actions.foreach(println)

val actions = for (character <- characters) yield character match { case Human(name) => name + " needs to be saved" case SuperHero(name, power) => name + " will save using " + power }

actions.foreach(println)

Page 43: Scala for Java Developers

Pattern matching and extracting just enough

43

val actions = for (character <- characters) yield character match { case Human(name) => name + " needs to be saved" case SuperHero(_, power) => "Could be saved using " + power }

actions.foreach(println)

// Programmer needs to be saved// Could be saved using money// Could be saved using testing

val actions = for (character <- characters) yield character match { case Human(name) => name + " needs to be saved" case SuperHero(_, power) => "Could be saved using " + power }

actions.foreach(println)

// Programmer needs to be saved// Could be saved using money// Could be saved using testing

Page 44: Scala for Java Developers

Regular expressions

44

val text = "Ramnivas Laddad"

val Name = """(\w+)\s+(\w+)""".r

val person = text match { case Name(first, last) => Some(new Person(first, last)) case _ => None}

println(person) // Some(Ramnivas Laddad)

val text = "Ramnivas Laddad"

val Name = """(\w+)\s+(\w+)""".r

val person = text match { case Name(first, last) => Some(new Person(first, last)) case _ => None}

println(person) // Some(Ramnivas Laddad)

Page 45: Scala for Java Developers

Options

45

val texts = List("Ramnivas Laddad", "foo", "Scott Andrews")

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))

val texts = List("Ramnivas Laddad", "foo", "Scott Andrews")

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))

Page 46: Scala for Java Developers

Options: flattening

46

val texts = List("Ramnivas Laddad", "foo", "Scott Andrews")

val peopleOptions = texts.map { _ match { case Name(first, last) => Some(new Person(first, last)) case _ => None }}

println(peopleOptions.flatten)// List(Ramnivas Laddad, Scott Andrews)

val texts = List("Ramnivas Laddad", "foo", "Scott Andrews")

val peopleOptions = texts.map { _ match { case Name(first, last) => Some(new Person(first, last)) case _ => None }}

println(peopleOptions.flatten)// List(Ramnivas Laddad, Scott Andrews)

Page 47: Scala for Java Developers

Options: flatMap

47

val texts = List("Ramnivas Laddad", "foo", "Scott Andrews")

val people = texts.flatMap { _ match { case Name(first, last) => Some(new Person(first, last)) case _ => None }}

println(people)// List(Ramnivas Laddad, Scott Andrews)

val texts = List("Ramnivas Laddad", "foo", "Scott Andrews")

val people = texts.flatMap { _ match { case Name(first, last) => Some(new Person(first, last)) case _ => None }}

println(people)// List(Ramnivas Laddad, Scott Andrews)

Page 48: Scala for Java Developers

Higher order functions

def process() : Unit = { retry(5) { ... }}

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)}

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)}

ThunkThunk

Page 49: Scala for Java Developers

Caching using Scala

def getQuoteGraph(stock: Stock, days: Int) : Array[Byte] = { cached("chart", stock.ticker + ":" + days) {

... Expensive calculation

}}

Page 50: Scala for Java Developers

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 } }}

Page 51: Scala for Java Developers

Transaction management

def findOrder(orderId: Long) : Order = { transactional(readOnly=true) { //... }} def updateOrder(order: Order) { transactional() { //... }}

51

Page 52: Scala for Java Developers

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

Page 53: Scala for Java Developers

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 } } }}

Page 54: Scala for Java Developers

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• …

54

Page 55: Scala for Java Developers

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

55

Be ready to be humbled

Page 56: Scala for Java Developers

Scala for Java Developers

© 2011 SpringOne 2GX. All rights reserved. Do not distribute without permission.