8. SCALA FEATURES
/JUST A FEW...
IMMUTABILITY EMPHASIS
FUNCTIONAL
OOP
Emphasis on immutable
data structures.
Transformations and
copies vs state
High Order functions and
great support for map,
flatmap, tabulate, filter,
foreach...
Traits, classes, case
classes, object...
ACTORS
MIXINS
IDIOMATIC
Built in support for this
high concurrency pattern
Attach behaviors at
runtime.
new Foo with Other
Flexible syntax, create
constructs, infix support,
everything is a value
val test = if(...)
val collection = for(...)
9. WHY LEARN SCALA?
/A MODERN LANGUAGE FOR MASSIVE
CONCURRENT APPLICATIONS IN THE CLOUD
11. IMMUTABILITY
In Java we tend to use Mutable structures
that need synchronization
JAVA
List<Integer> even = new ArrayList<Integer>();
for (String num : numbersAsStrings) {
int parsedInt = Integer.parseInt(num);
if (parsedInt % 2 == 0) {
ints.add(parsedInt);
}
}
In Scala we transform values into new values
SCALA
val ints = for (num <- numbersAsStrings; if num.toInt % 2 == 0) yield num.toInt
No need to synchronize in structures which
state is never modified
12. FUNCTIONAL
In Scala everything returns a value
scala> val myInt = 1
myInt: Int = 1
scala> def myFunction = "I don't need a return"
myFunction: String
scala> val result = for (n <- 0 to 10) yield n
result: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 2, 3, 4, 5, 6, 7, 8,
9, 10)
scala> val ifAreValues2 = if (true) "test"
ifAreValues2: Any = test
scala> val ifAreValues3 = if (true) "test" else "test2"
ifAreValues3: String = test
Functional style encourages to pipe the
results of functions and operations Vs
Imperative style
Iterator.continually(Option(queue.poll(1, TimeUnit.SECONDS))).takeWhile(_ => running)
foreach { msg => write(msg) }
13. OOP
In Scala everything is an Object and
supports a richer object model than Java
( multiple inheritance? :) )
Traits
trait Similarity {
def isSimilar(x: Any): Boolean
def isNotSimilar(x: Any): Boolean = !isSimilar(x)
}
Classes
class Point(xc: Int, yc: Int) extends Similarity {
var x: Int = xc
var y: Int = yc
def isSimilar(obj: Any) =
obj.isInstanceOf[Point] &&
obj.asInstanceOf[Point].x == x
}
Case Classes
case class Point(xc: Int, yc: Int) extends Similarity {
def isSimilar(obj: Any) = obj.isInstanceOf[Point] && obj.asInstanceOf[Point].x == x
}
Objects (singletons)
object TraitsTest {
val p1 = Point(2, 3)
val p2 = Point(2, 4)
val p3 = Point(3, 3)
println(p1.isNotSimilar(p2))
println(p1.isNotSimilar(p3))
println(p1.isNotSimilar(2))
}
14. ACTORS
Use actors for a high concurrent fault
tolerant distributed messaging system
/** invoke your army **/
val emailServiceActor = Akka.system.actorOf(
Props[EmailServiceActor].withRouter(
SmallestMailboxRouter(nrOfInstances = 50)
), name = "emailService"
)
/** send him to war **/
emailServiceActor ! emailMessage
/** this is the guy overseeing everything in the pentagon **/
class EmailServiceActor extends Actor{
override val supervisorStrategy =
OneForOneStrategy(maxNrOfRetries = 10) {
case emailException: EmailException => Restart
case unknownCase: Any => Stop
}
def receive = {
case message: Any => context.actorOf(Props[EmailServiceWorker]) ! message
}
}
/** And this one is the one in the field **/
class EmailServiceWorker extends Actor{
/** And this one is the one in the field **/
private var emailMessage: Option[EmailMessage] = None
def receive = {
case Some(email): EmailMessage => {
email.deliveryAttempts = email.deliveryAttempts + 1
email sendEmailSync()
}
case unexpectedMessage: Any => throw new Exception("can't handle %s" format(unexpectedMessage))
}
}
override def preRestart(reason: Throwable, message: Option[Any]) {
context.system.scheduler.scheduleOnce(emailMessage.get.retryOn, self, emailMessage.get)
}
15. MIXINS
What can fish do?
trait Swimmer { def swim = println("I'm swimming")}
class Fish extends Swimmer ...
trait Walker { def walk = println("I'm walking")}
val mudSkipper = new Fish() with Walker
mudSkipper.walk()
16. IDIOMATIC
DSL capable and idiomatic syntax
http://stackoverflow.com/questions/3186783/interesting-dsls-implemented-in-scala
/** Poll every second and stream messages **/
Iterator.continually(
Option(queue
.poll(1, TimeUnit.SECONDS)))
.takeWhile(_ => running) foreach { msg => write(msg) }
/** TDD and BDD ? **/
test("pop is invoked on an empty stack") {
val emptyStack = new Stack[String]
evaluating { emptyStack.pop() } should produce [NoSuchElementException]
emptyStack should be ('empty)
}
/** DB manipulation ? **/
def songCountByArtistId: Query[GroupWithMeasures[Long,Long]] =
from(artists, songs)((a,s) =>
where(a.id === s.artistId)
groupBy(a.id)
compute(count)
)
/** Json manipulation ? **/
("person" ->
("name" -> "Joe") ~
("age" -> 35) ~
("spouse" ->
("person" ->
("name" -> "Marilyn") ~
("age" -> 33)
)
)
)
/** Xml manipulation ? **/
val page =
<html>
<head>
<title>Hello XHTML world</title>
</head>
<body>
<h1>Hello world</h1>
</body>
</html>;
17. 1. HOF Higher Order Functions
A function that takes a function as argument
or returns another function
e.g. map & filter
28. Key differentiator
Higher Order Functions help with most Collection problems that you usually solve by
looping over and manually creating intermediate containers.
Transformed results stay immutable and thread safe.
No need to reinvent the wheel.
Code becomes readable and idiomatic
"betabeers" groupBy identity mapValues (_.size)
29. Other Powerful HOF’s examples
Sum
(1 to 1000).reduceLeft( _ + _ )
(1 to 1000).sum
Partition filter
val (passed, failed) = List(49, 58, 88, 90) partition ( _ > 60 )
min
List(14, 35, -7, 46, 98).min
max
List(14, 35, -7, 46, 98).max
Imperative iteration
(1 to 10) foreach (println)
Parallel Collections
(1 to 10).par foreach(_ => println(Thread.currentThread.getName))
30. Become a Scala Master
For comprehensions
Case Classes
Futures
Options
Traits
Either
Pattern Matching
Monads
Actors
DSL’s
...