My presentation at Silicon Valley Code Camp 13 (http://www.siliconvalley-codecamp.com/Session/2013/scala-for-java-developers). The target audience is Java developers who wants to get started with Scala.
2. @ramnivas
• Author of books and articles
– AspectJ in Action (1st and 2nd edition)
• Spring framework, Cloud Foundry
• Main interests
– Cloud computing
– Aspect-oriented programming
– Scala and functional programming
• Speaker at many professional conferences
– JavaOne, JavaPolis, SpringOne, Software Development, No Fluff Just Stuff,
EclipseCon, O’Reilly OSCON etc.
• Active involvement in AspectJ, Spring, and Cloud Foundry since
their early form
3. What is Scala
3
“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
4. Object-oriented
• Everything is an object
– No “primitives”
• Classes
– Same as Java, but concise
• Traits
– Interfaces done right
• Singletons
– Language-level concept
4
5. Statically typed
• Rich type system (by Java’s standard)
– Higher-kinded types
– Implicit conversions
– Type evidence
• Expressive type system
• Inferred types
5
6. 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 doesn’t force it
6
7. 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
7
8. Hello World: Scripting Style
$ scala hello-script.scala
Hello World
println("Hello World")
No compilation
9. Hello World: Porting of Java Code
$ scalac hello-java.scala
$ scala example.Main
Hello World
// hello-java.scala
package example
object Main {
def main(args: Array[String]) {
println("Hello World")
}
}
‘static’
Inferred
semicolons
10. Hello World: Using the App trait
$ scalac hello-app.scala
$ scala example.Main
Hello World
// hello-app.scala
package example
object Main extends App {
println("Hello World")
}
11. Simple Class
class Person
val p = new Person
Type
Inferred
Default
access: public
No curly
braces needed
(but allowed)
13. 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
14. Class with “getters”
class Person(val firstName: String,
val lastName: String)
val p = new Person("Ramnivas", "Laddad")
println(p.firstName)
Value
(Java ‘final’)
15. 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)
16. Extending a class
class Student(firstName: String,
lastName: String,
val grade: Int)
extends Person(firstName, lastName)
val s = new Student("Ramnivas", "Laddad", 1)
println(s.firstName)
println(s.grade)
17. 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
18. 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
19. Names in Scala
• Class, method, field names can contain non alpha-
numeric characters
– ::
– :::
– ~>
– f@#:
• Valuable if used judiciously
– DSLs
19
20. 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
20
21. 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
21
22. Traits: Interfaces done right
22
trait PartyGoer {
val age: Int
val yearsUntilLegalDrinking =
if (age >= 21) 0 else 21-age
}
class Student(firstName: String, lastName: String,
val age: Int, val grade: Int)
extends Person(firstName, lastName)
with PartyGoer
val s = new Student("a", "b", 17, 12)
s.yearsUntilLegalDrinking // 4
23. Collections
val people = List("John", "Jacob",
"Mike")
val firstPerson = people(0)
println(firstPerson) // John
24. Collections
val people = Array("John", "Jacob",
"Mike")
val firstPerson = people(0)
println(firstPerson) // John
26. Working with collections: for comprehension
26
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
27. Working with collections: for comprehension
27
for (person <- people if person startsWith "J") {
println(s"""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
28. 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 firstGraders = students.filter(
s => s.grade == 1)
println(firstGraders)
// List(first1 last1, first2 last2)
29. 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 inFirstGrade: Student => Boolean
= s => s.grade == 1
val firstGraders = students.filter(inFirstGrade)
// List(first1 last1, first2 last2)
30. 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 firstGraders
= students.filter(_.grade == 1)
println(firstGraders)
// List(first1 last1, first2 last2)
31. 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)
def inFirstGrade(s: Student) : Boolean
= s.grade == 1
val firstGraders = students.filter(inFirstGrade)
// List(first1 last1, first2 last2)
32. 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 (elementarySchoolers, middleSchoolers)
= students.partition(_.grade < 6)
println(elementarySchoolers)
println(middleSchoolers)
//List(first1 last1, first2 last2, first3 last3)
//List(first4 last4)
Tuple
33. 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 rollCall = students.map(_.firstName)
println(rollCall)
// List(first1, first2, first3, first4)
38. 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")
}
39. 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)
}
40. 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)))
41. Destutter using Pattern matching
41
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()
42. Case classes
• Useful in pattern matching
– “case”
• Offer many useful common methods
– equals()
– hashCode()
– toString
– copy()
42
43. Case classes
43
case class Human(name: String)
case class SuperHero(name: String, power: String)
val characters = List(Human("Programmer"),
SuperHero("Customer", "money"),
SuperHero("QA", "testing"))
44. Case classes and pattern matching
44
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)
45. Pattern matching and extracting just enough
45
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
46. Regular expressions
46
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)
47. Options
47
val texts =
List("Ramnivas Laddad", "foo", "Martin Odersky")
val peopleOptions = texts.map {
_ match {
case Name(first, last) =>
Some(new Person(first, last))
case _ => None
}
}
println(peopleOptions)
// List(Some(Ramnivas Laddad),
None,
Some(Martin Odersky))
48. Options: flattening
48
val texts =
List("Ramnivas Laddad", "foo", "Martin Odersky")
val peopleOptions = texts.map {
_ match {
case Name(first, last) =>
Some(new Person(first, last))
case _ => None
}
}
println(peopleOptions.flatten)
// List(Ramnivas Laddad, Martin Odersky)
49. Options: flatMap
49
val texts =
List("Ramnivas Laddad", "foo", "Martin Odersky")
val people = texts.flatMap {
_ match {
case Name(first, last) =>
Some(new Person(first, last))
case _ => None
}
}
println(people)
// List(Ramnivas Laddad, Martin Odersky)
50. Higher order functions
def process() : Unit = {
retry(5) {
...
}
}
def retry[T](maxRetry: Int)(thunk: => T) = {
def loop(thunk: => T, attempt: Int): T = {
try {
thunk
} catch {
case ex if (attempt < maxRetry) =>
loop(thunk, attempt + 1)
}
}
loop(thunk, 0)
}
Thunk
55. 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
}
}
}
}
56. There is more… a lot more
• Methods/functions
– Default parameters
– Named parameters
– Curried parameters
– Partial, partially-applied
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
• …
56
57. 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
– Will affect your non-Scala programming deeply
57
Be ready to be humbled
Be ready to have fun!