Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
Introduction to Scala 
Aleksandar Prokopec 
EPFL
Introduction to Scala
Pragmatic 
Since 
2003 
runs on the JVM 
Seamless Java 
interoperability 
Statically typed 
Production 
ready 
Martin Odersky 
Hybrid
Statically typed
runs on the JVM
Scala programs are fast.
OOP + FP
“I can honestly say if someone had shown me the Programming Scala book by Martin Odersky, Lex Spoon & Bill Venners back in 2003 I'd probably have never created Groovy.“ 
James Strachan, creator of Groovy
“If I were to pick a language to use today other than Java, it would be Scala.” 
James Gosling
Pragmatic
Scala is lightweight.
println(“Hello world!”)
scala> println(“Hello world!”) 
Hello world! 
REPL 
evaluating expressions on the fly
object MyApp extends App { 
println(“Hello world!”) 
} 
Compiled version
object MyApp extends App { 
println(“Hello world!”) 
} 
Singleton objects 
no more static methods
object MyApp { 
def main(args: Array[String]) { 
println(“Hello world!”) 
} 
} 
Declaring methods
object MyApp { 
def main(args: Array[String]) { 
var user: String = args(0) 
println(“Hello, ”+user+“!”) 
} 
} 
Declaring variables
object MyApp { 
def main(args: Array[String]) { 
val user: String = args(0) 
println(“Hello, ”+user+“!”) 
} 
} 
Declaring values 
prevents accidental changes
object MyApp { 
def main(args: Array[String]) { 
val user = args(0) 
println(“Hello, ”+user+“!”) 
} 
} 
Local type inference 
less… “typing”
class StringArrayFactory { 
def create: Array[String] = { 
val array: Array[String] = 
Array[String](“1”, “2”, “3”) 
array 
} 
} 
Local type inference 
less… “typing”
class StringArrayFactory { 
def create = { 
val array = Array(“1”, “2”, “3”) 
array 
} 
} 
Local type inference 
less… “typing”
// Scala 
class Person( 
var name: String, 
var age: Int 
) 
Declaring classes 
…concisely 
// Java 
public class Person { 
private String name; 
private int age; 
public Person(String name, int age) { 
this.name = name; 
this.age = age; 
} 
public String getName() { 
return name; 
} 
public int getAge() { 
return age; 
} 
public void setName(String name) { 
this.name = name; 
} 
public void setAge(int age) { 
this.age = age; 
} 
}
Scala is object-oriented.
object Foo { 
val b = new ArrayBuffer[Any] 
} 
Object-oriented 
everything’s an object
Object-oriented 
everything’s an object 
Any 
AnyRef 
AnyVal 
String 
Boolean 
Char 
Int
object Foo { 
val b = new ArrayBuffer[Any] 
b += 1 
b += 1.toString 
b += Foo 
println(b) 
} 
Object-oriented 
everything’s an object
1 + 2 
1.+(2) 
Array(1, 2, 3) ++ Array(4, 5, 6) 
Array(1, 2, 3).++(Array(4, 5, 6)) 
1 :: List(2, 3) 
List(2, 3).::(1) 
Operator overloading 
operators are methods
trait Iterator[T] { 
def next(): T 
def hasNext: Boolean 
} 
Declaring traits 
traits are like interfaces
trait Iterator[T] { 
def next(): T 
def hasNext: Boolean 
def printAll() = 
while (hasNext) println(next()) 
} 
Declaring traits 
traits are rich
trait Animal 
Multiple inheritance 
traits are composable
trait Animal 
trait Mammal extends Animal { 
def think() = println(“hm...”) 
} 
Multiple inheritance 
traits are composable
trait Animal 
trait Mammal extends Animal { 
def think() = println(“hm...”) 
} 
trait Bird extends Animal { 
def layEgg() = System.createEgg() 
} 
Multiple inheritance 
traits are composable
Introduction to Scala
trait Animal 
trait Mammal extends Animal { 
def think() = println(“hm...”) 
} 
trait Bird extends Animal { 
def layEgg() = System.createEgg() 
} 
class Platypus extends Bird with Mammal 
Mixin composition 
traits are composable
trait Animal 
trait Reptile extends Animal { 
def layInTheSun: Unit = {} 
} 
class Dog(name: String) extends Mammal 
new Dog(“Nera”) with Reptile 
Dynamic mixin composition 
…or composition “on the fly”
Cake pattern
trait Logging { 
def log(msg: String) 
} 
trait AnsweringMachine { 
self: Logging with DAO with Protocol => 
log(“Initializing.”) 
... 
} 
Self-types 
to express requirements
trait ConsoleLogging { 
def log(msg: String) = println(msg) 
} 
class LocalAnsweringMachine 
extends AnsweringMachine 
with ConsoleLogging 
with H2DAO 
with JabberProtocol 
Cake pattern 
layers above layers
Scala is functional.
(x: Int) => x + 1 
First class functions
val doub: Int => Int = (x: Int) => x * 2 
doub(1) 
 2 
First class functions 
functions are objects too
val doub = (x: Int) => x * 2 
List(1, 2, 3).map(doub) 
 List(2, 4, 6) 
First class functions 
as higher order parameters
List[Int](1, 2, 3).map((x: Int) => x * 2) 
// more type inference 
List(1, 2, 3).map(x => x * 2) 
// or even shorter 
List(1, 2, 3).map(_ * 2) 
Functions with sugar 
make code sweeter
var step = 1 
val inc = x => x + step 
inc(5) 
 6 
step = 2 
inc(5) 
 7 
Closures 
functions that “capture” their environment
// Java 
button.addMouseListener(new MouseAdapter() { 
public void mouseEntered(MouseEvent e) { 
System.out.println(e); 
} 
} 
// Scala 
listenTo(button) 
reactions += { case e => println(e) } 
First class functions 
because you write them in Java all the time
Pattern matching
Pattern matching 
…is concise 
// Scala 
reactions += { 
case m: MouseEntered => 
println(“I see it!”) 
case m: MouseExited => 
println(“Lost it.”) 
case m: MouseClicked => 
println(“Poked!”) 
} 
// Java 
button.addMouseListener(new MouseAdapter() { 
public void mousePressed(MouseEvent e) {} 
public void mouseReleased(MouseEvent e) {} 
public void mouseEntered(MouseEvent e) {} 
public void mouseEntered(MouseEvent e) { 
System.out.println(“I see it!”); 
} 
public void mouseExited(MouseEvent e) { 
System.out.println(“Lost it.”); 
} 
public void mouseClicked(MouseEvent e) { 
System.out.println(“Poked!”); 
} 
} 
// ...alternative - isinstanceof
trait Tree 
case class Node(l: Tree, r: Tree) 
extends Tree 
case object Leaf 
extends Tree 
Pattern matching 
…is precise
def b(t: Tree): Int = t match { 
case Node(Leaf, Node(_, _)) | 
Node(Node(_, _), Leaf) => -1 
case Node(l, r) => 
val (ld, rd) = (b(l), b(r)) 
if (ld == rd) ld + 1 else -1 
case Leaf => 0 
case _ => error(“Unknown tree!”) 
} 
Pattern matching 
…is precise
sealed trait Tree 
... 
def b(t: Tree): Int = t match { 
case Node(Leaf, Node(_, _)) | 
Node(Node(_, _), Leaf) => -1 
case Node(l, r) => 
val (ld, rd) = (b(l), b(r)) 
if (ld == rd) ld + 1 else -1 
case Leaf => 0 
} 
Pattern matching 
…is exhaustive
def matchingMeSoftly(a: Any): Any = 
a match { 
case 11 => “eleven” 
case s: String => “’%s’”.format(s) 
case <tag>{t}</tag> => t 
case Array(1, 2, 3) => “1, 2, 3” 
case head :: tail => tail 
case _ => null 
} 
Pattern matching 
…is extensible
Lazyness
lazy values 
don’t compute if there’s no demand 
class User(id: Int) { 
lazy val followernum = 
from(followers)(f => 
where(id === f.fid) 
compute(countDistinct(f.fid)) 
) 
}
Call by name 
evaluate only when you have to 
def withErrorOut(body: =>Unit) = { 
val old = Console.out 
Console.setOut(Console.err) 
try body 
finally Console.setOut(old) 
} 
... 
withErrorOut { 
if (n < 0) println(“n too small”) 
}
Streams 
lazy lists 
e = Σ 1/n! 
= 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + …
Streams 
lazy lists 
e = Σ 1/n! 
= 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + … 
0! 
?
Streams 
lazy lists 
e = Σ 1/n! 
= 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + … 
0! 
1! 
2! 
3! 
? 
0! 
?
Streams 
lazy lists 
e = Σ 1/n! 
= 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + … 
0! 
1! 
2! 
3! 
? 
0! 
? 
0! 
1/1! 
1/2! 
1/3! 
?
Streams 
lazy lists 
def fact(n: Int, p: Int): Stream[Int] = 
p #:: fact(n + 1, p * (n + 1)) 
val factorials = fact(0, 1) 
val e = factorials.map(1./_).take(10).sum
Scala is expressive.
for comprehensions 
traverse anything 
for (x <- List(1, 2, 3)) println(x) 
List(1, 2, 3).foreach(x => println(x)) 
for (x <- 0 until 10) println(x) 
(0 until 10).foreach(x => println(x)) 
Range(0, 10, 1).foreach(x => println(x))
for comprehensions 
map anything 
for (x <- List(1, 2, 3)) yield x * 2 
List(1, 2, 3).map(x => x * 2) 
for (x <- List(1, 2); y <- List(1, 2)) 
yield x * y 
List(1, 2).flatMap(x => 
List(1, 2).map(y => x * y) 
) 
 List(1, 2, 2, 4)
for comprehensions 
like SQL queries 
for { 
p <- people 
if p.age > 25 
s <- schools 
if p.degree == s.degree 
} yield (p, s) 
// pairs of people older than 25 and 
// schools they possibly attended
Collections 
easy to create 
val phonebook = Map( 
“Jean” -> “123456”, 
“Damien” -> “666666”) 
val meetings = ArrayBuffer( 
“Dante”, “Damien”, “Sophie”) 
println(phonebook(meetings(1)))
Collections 
high-level combinators 
// Java 
boolean isOk = true 
for (int i = 0; i < name.length(); i++) { 
if (isLetterOrDigit(name.charAt(i)) { 
isOk = false; 
break; 
} 
}
Collections 
high-level combinators 
// Scala 
name.forall(_.isLetterOrDigit)
Collections 
high-level combinators 
// count the total number of different 
// surnames shared by at least 2 adults 
people
Collections 
high-level combinators 
// count the total number of different 
// surnames shared by at least 2 adults 
people.filter(_.age >= 18)
Collections 
high-level combinators 
// count the total number of different 
// surnames shared by at least 2 adults 
people.filter(_.age >= 18) 
.groupBy(_.surname): Map[String, List[Person]]
Collections 
high-level combinators 
// count the total number of different 
// surnames shared by at least 2 adults 
people.filter(_.age >= 18) 
.groupBy(_.surname): Map[String, List[Person]] 
.count { case (s, l) => l.size >= 2 }
Lists 
an immutable sequence 
val countdown = List(3, 2, 1) 
3 
2 
1 
countdown
Lists 
an immutable sequence 
val countdown = List(3, 2, 1) 
val longer = 4 :: countdown 
3 
2 
1 
4 
countdown 
longer
Lists 
an immutable sequence 
val countdown = List(3, 2, 1) 
val longer = 4 :: countdown 
val fast = 10 :: countdown 
3 
2 
1 
4 
10 
countdown 
longer 
fast
Lists 
an immutable sequence 
val countdown = List(3, 2, 1) 
val longer = 4 :: countdown 
val fast = 10 :: countdown 
val withzero = countdown ::: List(0) 
3 
2 
1 
4 
10 
3 
2 
1 
0 
countdown 
longer 
fast 
withzero
Buffers 
mutable sequences 
val b = ArrayBuffer(1, 2, 3) 
b += 4 
b += 5 
b += 6 
 ArrayBuffer(1, 2, 3, 4, 5, 6)
Maps 
mutable or immutable, sorted or unsorted 
import collection._ 
val m = mutable.Map(“Heidfeld” -> 1, 
“Schumacher” -> 2) 
m += “Hakkinen” -> 3 
val im = immutable.Map(“Schumacher” -> 1)
Hash tries 
persistence through efficient structural sharing 
val im0: Map[Int, Int] = ... 
im0
Hash tries 
persistence through efficient structural sharing 
val im0: Map[Int, Int] = ... 
val im1 = im0 + (1 -> 1) 
im0 
im1
Hash tries 
persistence through efficient structural sharing 
val im0: Map[Int, Int] = ... 
val im1 = im0 + (1 -> 1) 
val im2 = im1 + (2 -> 2) 
im0 
im1 
im2
Hash tries 
persistence through efficient structural sharing 
val im0: Map[Int, Int] = ... 
val im1 = im0 + (1 -> 1) 
val im2 = im1 + (2 -> 2) 
val im3 = im2 + (3 -> 6) 
im0 
im1 
im2 
im3
Hash tries 
persistence through efficient structural sharing 
im0 
im1 
im2 
im3 
2x-3x slower lookup 
2x faster iteration
Parallel collections 
parallelize bulk operations on collections 
def cntEqlen(m: Map[String, String]) = { 
m.par.count { 
case (n, s) => n.length == s.length 
} 
} 
// be careful with side-effects
Scala is extensible.
One ring to rule them all.
actors 
road to safer concurrency 
val a = actor { 
react { 
case i: Int => println(i) 
} 
} 
... 
a ! 5
Custom control flow 
it’s all about control 
def myWhile(c: =>Boolean)(b: =>Unit) { 
if (c) { 
b 
myWhile(c)(b) 
} 
}
Custom control flow 
it’s all about control 
@tailrec 
def myWhile(c: =>Boolean)(b: =>Unit) { 
if (c) { 
b 
myWhile(c)(b) 
} 
}
Custom control flow 
it’s all about control 
@tailrec 
def myWhile(c: =>Boolean)(b: =>Unit) { 
if (c) { 
b 
myWhile(c)(b) 
} 
} 
var i = 0 
myWhile (i < 5) { 
i += 1 
}
ARM 
automatic resource management 
withFile (“~/.bashrc”) { f => 
for (l <- f.lines) { 
if (“#”.r.findFirstIn(l) != None) 
println(l) 
} 
}
ScalaTest 
behavioral testing framework 
“A list” should { 
“be a double reverse of itself” in { 
val ls = List(1, 2, 3, 4, 5, 6) 
ls.reverse.reverse should equal (ls) 
} 
}
BaySick 
Basic DSL in Scala 
10 PRINT “Baysick Lunar Lander v0.9” 
20 LET ('dist := 100) 
30 LET ('v := 1) 
40 LET ('fuel := 1000) 
50 LET ('mass := 1000) 
...
implicit conversions 
augmenting types with new operations 
‘a’.toUpperCase
implicit conversions 
augmenting types with new operations 
implicit def charOps(c: Char) = new { 
def toUpperCase = 
if (c >= ‘a’ && c <= ‘z’) 
(c – 32).toChar 
else c 
} 
... 
‘a’.toUpperCase
Pimp my library
implicit conversions 
pimping your libraries since 2006 
import scalaj.collection._ 
val list = new java.util.ArrayList[Int] 
list.add(1) 
list.add(2) 
list.add(3) 
... 
for (x <- list) yield x * 2
implicit conversions 
pimping your libraries since 2006 
import scalaj.collection._ 
val list = new java.util.ArrayList[Int] 
list.add(1) 
list.add(2) 
list.add(3) 
... 
for (x <- list) yield x * 2 
// list.map(x => x * 2)
implicit conversions 
pimping your libraries since 2006 
import scalaj.collection._ 
val list = new java.util.ArrayList[Int] 
list.add(1) 
list.add(2) 
list.add(3) 
... 
for (x <- list) yield x * 2 
// jlist2slist(list).map(x => x * 2)
implicit arguments 
restricting operations on types 
val is = SortedSet(1, 2, 3) 
case class Man(id: Int) 
... 
implicit object MenOrd extends Ordering[Man] { 
def compare(x: Man, y: Man) = x.id – y.id 
} 
val ms = SortedSet(Person(1), Person(2))
STM 
software transactional memory 
val account1 = cell[Int] 
val account2 = cell[Int] 
atomic { implicit txn => 
if (account2() >= 50) { 
account1 += 50 
account2 -= 50 
} 
}
Scala has support.
Building 
Ant 
SBT 
Maven
SBT 
simple build tool 
> compile 
... 
> ~compile 
... 
> test 
... 
> package
SBT 
project definition written in Scala 
val scalatest = 
“org.scala-tools.testing” % 
“scalatest” % “0.9.5” 
... 
> reload 
[INFO] Building project ... 
[INFO] using sbt.Default ... 
> update
Tools: IDEs 
Eclipse 
Netbeans 
IntelliJ IDEA 
Emacs ENSIME 
JEdit
Web frameworks
Used by...
Thank you!

More Related Content

Introduction to Scala

  • 1. Introduction to Scala Aleksandar Prokopec EPFL
  • 3. Pragmatic Since 2003 runs on the JVM Seamless Java interoperability Statically typed Production ready Martin Odersky Hybrid
  • 8. “I can honestly say if someone had shown me the Programming Scala book by Martin Odersky, Lex Spoon & Bill Venners back in 2003 I'd probably have never created Groovy.“ James Strachan, creator of Groovy
  • 9. “If I were to pick a language to use today other than Java, it would be Scala.” James Gosling
  • 13. scala> println(“Hello world!”) Hello world! REPL evaluating expressions on the fly
  • 14. object MyApp extends App { println(“Hello world!”) } Compiled version
  • 15. object MyApp extends App { println(“Hello world!”) } Singleton objects no more static methods
  • 16. object MyApp { def main(args: Array[String]) { println(“Hello world!”) } } Declaring methods
  • 17. object MyApp { def main(args: Array[String]) { var user: String = args(0) println(“Hello, ”+user+“!”) } } Declaring variables
  • 18. object MyApp { def main(args: Array[String]) { val user: String = args(0) println(“Hello, ”+user+“!”) } } Declaring values prevents accidental changes
  • 19. object MyApp { def main(args: Array[String]) { val user = args(0) println(“Hello, ”+user+“!”) } } Local type inference less… “typing”
  • 20. class StringArrayFactory { def create: Array[String] = { val array: Array[String] = Array[String](“1”, “2”, “3”) array } } Local type inference less… “typing”
  • 21. class StringArrayFactory { def create = { val array = Array(“1”, “2”, “3”) array } } Local type inference less… “typing”
  • 22. // Scala class Person( var name: String, var age: Int ) Declaring classes …concisely // Java public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } }
  • 24. object Foo { val b = new ArrayBuffer[Any] } Object-oriented everything’s an object
  • 25. Object-oriented everything’s an object Any AnyRef AnyVal String Boolean Char Int
  • 26. object Foo { val b = new ArrayBuffer[Any] b += 1 b += 1.toString b += Foo println(b) } Object-oriented everything’s an object
  • 27. 1 + 2 1.+(2) Array(1, 2, 3) ++ Array(4, 5, 6) Array(1, 2, 3).++(Array(4, 5, 6)) 1 :: List(2, 3) List(2, 3).::(1) Operator overloading operators are methods
  • 28. trait Iterator[T] { def next(): T def hasNext: Boolean } Declaring traits traits are like interfaces
  • 29. trait Iterator[T] { def next(): T def hasNext: Boolean def printAll() = while (hasNext) println(next()) } Declaring traits traits are rich
  • 30. trait Animal Multiple inheritance traits are composable
  • 31. trait Animal trait Mammal extends Animal { def think() = println(“hm...”) } Multiple inheritance traits are composable
  • 32. trait Animal trait Mammal extends Animal { def think() = println(“hm...”) } trait Bird extends Animal { def layEgg() = System.createEgg() } Multiple inheritance traits are composable
  • 34. trait Animal trait Mammal extends Animal { def think() = println(“hm...”) } trait Bird extends Animal { def layEgg() = System.createEgg() } class Platypus extends Bird with Mammal Mixin composition traits are composable
  • 35. trait Animal trait Reptile extends Animal { def layInTheSun: Unit = {} } class Dog(name: String) extends Mammal new Dog(“Nera”) with Reptile Dynamic mixin composition …or composition “on the fly”
  • 37. trait Logging { def log(msg: String) } trait AnsweringMachine { self: Logging with DAO with Protocol => log(“Initializing.”) ... } Self-types to express requirements
  • 38. trait ConsoleLogging { def log(msg: String) = println(msg) } class LocalAnsweringMachine extends AnsweringMachine with ConsoleLogging with H2DAO with JabberProtocol Cake pattern layers above layers
  • 40. (x: Int) => x + 1 First class functions
  • 41. val doub: Int => Int = (x: Int) => x * 2 doub(1)  2 First class functions functions are objects too
  • 42. val doub = (x: Int) => x * 2 List(1, 2, 3).map(doub)  List(2, 4, 6) First class functions as higher order parameters
  • 43. List[Int](1, 2, 3).map((x: Int) => x * 2) // more type inference List(1, 2, 3).map(x => x * 2) // or even shorter List(1, 2, 3).map(_ * 2) Functions with sugar make code sweeter
  • 44. var step = 1 val inc = x => x + step inc(5)  6 step = 2 inc(5)  7 Closures functions that “capture” their environment
  • 45. // Java button.addMouseListener(new MouseAdapter() { public void mouseEntered(MouseEvent e) { System.out.println(e); } } // Scala listenTo(button) reactions += { case e => println(e) } First class functions because you write them in Java all the time
  • 47. Pattern matching …is concise // Scala reactions += { case m: MouseEntered => println(“I see it!”) case m: MouseExited => println(“Lost it.”) case m: MouseClicked => println(“Poked!”) } // Java button.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseEntered(MouseEvent e) { System.out.println(“I see it!”); } public void mouseExited(MouseEvent e) { System.out.println(“Lost it.”); } public void mouseClicked(MouseEvent e) { System.out.println(“Poked!”); } } // ...alternative - isinstanceof
  • 48. trait Tree case class Node(l: Tree, r: Tree) extends Tree case object Leaf extends Tree Pattern matching …is precise
  • 49. def b(t: Tree): Int = t match { case Node(Leaf, Node(_, _)) | Node(Node(_, _), Leaf) => -1 case Node(l, r) => val (ld, rd) = (b(l), b(r)) if (ld == rd) ld + 1 else -1 case Leaf => 0 case _ => error(“Unknown tree!”) } Pattern matching …is precise
  • 50. sealed trait Tree ... def b(t: Tree): Int = t match { case Node(Leaf, Node(_, _)) | Node(Node(_, _), Leaf) => -1 case Node(l, r) => val (ld, rd) = (b(l), b(r)) if (ld == rd) ld + 1 else -1 case Leaf => 0 } Pattern matching …is exhaustive
  • 51. def matchingMeSoftly(a: Any): Any = a match { case 11 => “eleven” case s: String => “’%s’”.format(s) case <tag>{t}</tag> => t case Array(1, 2, 3) => “1, 2, 3” case head :: tail => tail case _ => null } Pattern matching …is extensible
  • 53. lazy values don’t compute if there’s no demand class User(id: Int) { lazy val followernum = from(followers)(f => where(id === f.fid) compute(countDistinct(f.fid)) ) }
  • 54. Call by name evaluate only when you have to def withErrorOut(body: =>Unit) = { val old = Console.out Console.setOut(Console.err) try body finally Console.setOut(old) } ... withErrorOut { if (n < 0) println(“n too small”) }
  • 55. Streams lazy lists e = Σ 1/n! = 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + …
  • 56. Streams lazy lists e = Σ 1/n! = 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + … 0! ?
  • 57. Streams lazy lists e = Σ 1/n! = 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + … 0! 1! 2! 3! ? 0! ?
  • 58. Streams lazy lists e = Σ 1/n! = 1/0! + 1/1! + 1/2! + 1/3! + 1/4! + … 0! 1! 2! 3! ? 0! ? 0! 1/1! 1/2! 1/3! ?
  • 59. Streams lazy lists def fact(n: Int, p: Int): Stream[Int] = p #:: fact(n + 1, p * (n + 1)) val factorials = fact(0, 1) val e = factorials.map(1./_).take(10).sum
  • 61. for comprehensions traverse anything for (x <- List(1, 2, 3)) println(x) List(1, 2, 3).foreach(x => println(x)) for (x <- 0 until 10) println(x) (0 until 10).foreach(x => println(x)) Range(0, 10, 1).foreach(x => println(x))
  • 62. for comprehensions map anything for (x <- List(1, 2, 3)) yield x * 2 List(1, 2, 3).map(x => x * 2) for (x <- List(1, 2); y <- List(1, 2)) yield x * y List(1, 2).flatMap(x => List(1, 2).map(y => x * y) )  List(1, 2, 2, 4)
  • 63. for comprehensions like SQL queries for { p <- people if p.age > 25 s <- schools if p.degree == s.degree } yield (p, s) // pairs of people older than 25 and // schools they possibly attended
  • 64. Collections easy to create val phonebook = Map( “Jean” -> “123456”, “Damien” -> “666666”) val meetings = ArrayBuffer( “Dante”, “Damien”, “Sophie”) println(phonebook(meetings(1)))
  • 65. Collections high-level combinators // Java boolean isOk = true for (int i = 0; i < name.length(); i++) { if (isLetterOrDigit(name.charAt(i)) { isOk = false; break; } }
  • 66. Collections high-level combinators // Scala name.forall(_.isLetterOrDigit)
  • 67. Collections high-level combinators // count the total number of different // surnames shared by at least 2 adults people
  • 68. Collections high-level combinators // count the total number of different // surnames shared by at least 2 adults people.filter(_.age >= 18)
  • 69. Collections high-level combinators // count the total number of different // surnames shared by at least 2 adults people.filter(_.age >= 18) .groupBy(_.surname): Map[String, List[Person]]
  • 70. Collections high-level combinators // count the total number of different // surnames shared by at least 2 adults people.filter(_.age >= 18) .groupBy(_.surname): Map[String, List[Person]] .count { case (s, l) => l.size >= 2 }
  • 71. Lists an immutable sequence val countdown = List(3, 2, 1) 3 2 1 countdown
  • 72. Lists an immutable sequence val countdown = List(3, 2, 1) val longer = 4 :: countdown 3 2 1 4 countdown longer
  • 73. Lists an immutable sequence val countdown = List(3, 2, 1) val longer = 4 :: countdown val fast = 10 :: countdown 3 2 1 4 10 countdown longer fast
  • 74. Lists an immutable sequence val countdown = List(3, 2, 1) val longer = 4 :: countdown val fast = 10 :: countdown val withzero = countdown ::: List(0) 3 2 1 4 10 3 2 1 0 countdown longer fast withzero
  • 75. Buffers mutable sequences val b = ArrayBuffer(1, 2, 3) b += 4 b += 5 b += 6  ArrayBuffer(1, 2, 3, 4, 5, 6)
  • 76. Maps mutable or immutable, sorted or unsorted import collection._ val m = mutable.Map(“Heidfeld” -> 1, “Schumacher” -> 2) m += “Hakkinen” -> 3 val im = immutable.Map(“Schumacher” -> 1)
  • 77. Hash tries persistence through efficient structural sharing val im0: Map[Int, Int] = ... im0
  • 78. Hash tries persistence through efficient structural sharing val im0: Map[Int, Int] = ... val im1 = im0 + (1 -> 1) im0 im1
  • 79. Hash tries persistence through efficient structural sharing val im0: Map[Int, Int] = ... val im1 = im0 + (1 -> 1) val im2 = im1 + (2 -> 2) im0 im1 im2
  • 80. Hash tries persistence through efficient structural sharing val im0: Map[Int, Int] = ... val im1 = im0 + (1 -> 1) val im2 = im1 + (2 -> 2) val im3 = im2 + (3 -> 6) im0 im1 im2 im3
  • 81. Hash tries persistence through efficient structural sharing im0 im1 im2 im3 2x-3x slower lookup 2x faster iteration
  • 82. Parallel collections parallelize bulk operations on collections def cntEqlen(m: Map[String, String]) = { m.par.count { case (n, s) => n.length == s.length } } // be careful with side-effects
  • 84. One ring to rule them all.
  • 85. actors road to safer concurrency val a = actor { react { case i: Int => println(i) } } ... a ! 5
  • 86. Custom control flow it’s all about control def myWhile(c: =>Boolean)(b: =>Unit) { if (c) { b myWhile(c)(b) } }
  • 87. Custom control flow it’s all about control @tailrec def myWhile(c: =>Boolean)(b: =>Unit) { if (c) { b myWhile(c)(b) } }
  • 88. Custom control flow it’s all about control @tailrec def myWhile(c: =>Boolean)(b: =>Unit) { if (c) { b myWhile(c)(b) } } var i = 0 myWhile (i < 5) { i += 1 }
  • 89. ARM automatic resource management withFile (“~/.bashrc”) { f => for (l <- f.lines) { if (“#”.r.findFirstIn(l) != None) println(l) } }
  • 90. ScalaTest behavioral testing framework “A list” should { “be a double reverse of itself” in { val ls = List(1, 2, 3, 4, 5, 6) ls.reverse.reverse should equal (ls) } }
  • 91. BaySick Basic DSL in Scala 10 PRINT “Baysick Lunar Lander v0.9” 20 LET ('dist := 100) 30 LET ('v := 1) 40 LET ('fuel := 1000) 50 LET ('mass := 1000) ...
  • 92. implicit conversions augmenting types with new operations ‘a’.toUpperCase
  • 93. implicit conversions augmenting types with new operations implicit def charOps(c: Char) = new { def toUpperCase = if (c >= ‘a’ && c <= ‘z’) (c – 32).toChar else c } ... ‘a’.toUpperCase
  • 95. implicit conversions pimping your libraries since 2006 import scalaj.collection._ val list = new java.util.ArrayList[Int] list.add(1) list.add(2) list.add(3) ... for (x <- list) yield x * 2
  • 96. implicit conversions pimping your libraries since 2006 import scalaj.collection._ val list = new java.util.ArrayList[Int] list.add(1) list.add(2) list.add(3) ... for (x <- list) yield x * 2 // list.map(x => x * 2)
  • 97. implicit conversions pimping your libraries since 2006 import scalaj.collection._ val list = new java.util.ArrayList[Int] list.add(1) list.add(2) list.add(3) ... for (x <- list) yield x * 2 // jlist2slist(list).map(x => x * 2)
  • 98. implicit arguments restricting operations on types val is = SortedSet(1, 2, 3) case class Man(id: Int) ... implicit object MenOrd extends Ordering[Man] { def compare(x: Man, y: Man) = x.id – y.id } val ms = SortedSet(Person(1), Person(2))
  • 99. STM software transactional memory val account1 = cell[Int] val account2 = cell[Int] atomic { implicit txn => if (account2() >= 50) { account1 += 50 account2 -= 50 } }
  • 102. SBT simple build tool > compile ... > ~compile ... > test ... > package
  • 103. SBT project definition written in Scala val scalatest = “org.scala-tools.testing” % “scalatest” % “0.9.5” ... > reload [INFO] Building project ... [INFO] using sbt.Default ... > update
  • 104. Tools: IDEs Eclipse Netbeans IntelliJ IDEA Emacs ENSIME JEdit