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
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
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 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
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)
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)
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)
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)
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
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)
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" ) }
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) }
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 case class Human(name: String) case class SuperHero(name: String, power: String) val characters = List(Human( "Programmer" ), SuperHero( "Customer" , "money" ), SuperHero( "QA" , "testing" ))
Case classes and pattern matching 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)
Pattern matching and extracting just enough 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
Regular expressions val text = "Ramnivas Laddad" val Name = """(+)+(+)""" .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( "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))
Options: flattening 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)
Options: flatMap 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)
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