SlideShare ist ein Scribd-Unternehmen logo
1 von 107
Downloaden Sie, um offline zu lesen
A SCALABLE LANGUAGE
Innar Made
TOPICS
JVM languages landscape
OOP
FP
Pattern matching
Pimp my library
XML
Parallel collections
Actors
Scala in real world
JVMLANGUAGES
LANDSCAPE
What else is there besides Java?
JAVAPROSANDCONS
Pros
Simple language
Portable
Lot's of libraries and frameworks
Big community
Cons
Class based OOP is used for everything, even when
inappropriate, due to lack of support for anything else
Lot's of boilerplate code
Favors mutability
WHYTRYOTHER JVM
LANGUAGES?
Those languages tend to be more expressive - say
more, write less
Discover new ways of thinking about problems
Use the existing Java libraries/frameworks to fill in the
gaps
MEETSCALA
OVERVIEW
Created by Martin Odersky
Appeared around 2003
Statically typed
Type inference
Mixture of OOP and FP
Actor concurrency
Very good Java interop
Currently the most widely adopted alternate JVM
language
OOPIN SCALA
PERSON IN JAVA
import static java.lang.String.format;
public class Person {
public final String name;
public final int age;
public Person(final String name, final int age) {
this.name = name;
this.age = age;
}
public String greet() {
return format("Hello, my name is %s", name);
}
public String greet(final Person person) {
return format("Hello, %s, my name is %s", person.name, name);
}
@Override
public String toString() {
return format("name=%s, age=%d", name, age);
}
}
SAMEPERSON IN SCALA
class Person(val name: String, val age: Int) {
def greet = "Hello, my name is %s".format(name)
def greet(person: Person) =
"Hello, %s, my name is %s".format(person.name, name)
override def toString = "name=%s, age=%d".format(name, age)
}
JOE,MEETJOE
val joe = new Person("Joe", 35)
val age = joe.age
val olderJoe = new Person(joe.name, age + 1)
joe.greet(olderJoe)
joe greet olderJoe
TYPEINFERENCE
Scala code looks a bit like scripting language, right?
That is because Scala compiler can sometimes infer the
types. In that case you don't need to declare types
explicitly. But you can, if you want.
val joe = new Person("Joe", 35)
val age = joe.age
WITHEXPLICITTYPES
val joe: Person = new Person("Joe", 35)
val age: Int = joe.age
val olderJoe: Person = new Person(joe.name, age + 1)
joe greet olderJoe
def makeFriends(p1: Person, p2: Person): String =
"%s and %s became good friends".format(p1.name, p2.name)
makeFriends(joe, olderJoe)
INHERITANCE
abstract class A {
def call = "A"
}
trait B {
def call = "B"
}
trait C {
def call = "C"
}
class ABC extends A with B with C {
override def call = super.call
}
val abc = new ABC
println(abc.call) //prints C
ANONYMOUSCLASSES
trait Jedi {
def useForceOn(p: Person): String
def greet(p: Person) =
"May the force be with you, %s!".format(p.name)
}
trait ForceLightning {
def useForceOn(p: Person) =
"%s gets shocked with force lightning"
}
val obiWan = new Person("Obi Wan", 71) with Jedi {
override def greet(p: Person) = super.greet(p)
def useForceOn(p: Person): String =
"These are not the droids you're looking for, %s".format(p.name)
}
val anakin = new Person("Anakin", 27) with Jedi with ForceLightning {
override def greet(p: Person) =
"Join the dark side, %s!".format(p.name)
}
GENERICS
class Pair[A,B](val first: A, val second: B) {
def add[C](third: C) = new Triple(first, second, third)
}
class Triple[A,B,C](val first: A, val second: B, val third: C)
val p = new Pair("Joe", 36)
val t = p.add('MALE)
COMPANION OBJECT
class Pair[A, B](val first: A, val second: B)
object Pair {
def apply[A, B](first: A, second: B) = new Pair(first, second)
def empty[A, B] = new Pair[Option[A], Option[B]](None, None)
}
//Pair[String, Int]
val p1 = Pair("Joe", 36)
//Pair[Option[String], Option[Int]]
val p2 = Pair.empty[String, Int]
FUNCTIONAL
PROGRAMMING
FP
Using side effect free functions for computations
Avoiding mutable data structures and variables
First-class functions
Recursion
FPBENEFITS
Side effect free functions are easy to test and
understand.
Functions are more reusable than classes
Makes concurrency and parallelism easier
More declarative and concise code
Stop worrying what objects got mutated between
method calls and instead start combining functions to
transform the input to the desired output
OOP+FP
OOP generally is about nouns (Person, Car, Record)
FP is about verbs (filter, map, reduce, group, zip)
OOP offers a way to structure
FP offers a way to compute
In large projects we benefit from both
FPUSECASES
Good fit:
Transforming data
Systems where you need concurrency and parallelism
Not a good fit:
UI (although, rumor has it that FRP makes UI
programming easy)
IO (read/write file, query the DB, make a HTTP request)
PS! Above scenarios are all good fit for Scala as you can
easily change programming paradigms
FIRST-CLASSFUNCTIONS
FUNCTIONSAS
PARAMETERS
filter, map and reduce are functions defined on the List
object
filter expects a function of A => Boolean
map expects a function of A => B
reduce expects a function of (A, A) => A
def isEven(x: Int) = x % 2 == 0
def pow3(x: Int) = x * x * x
def add(x: Int, y: Int) = x + y
val numbers = List(1, 2, 3, 4)
numbers.filter(isEven).map(pow3).reduce(add) //72
FUNCTION LITERALS
All FP languages support function literals since it's the
central part of the paradigm
val numbers = List(1, 2, 3, 4)
val evens = numbers.filter(n => n % 2 == 0)
val powOf3s = evens.map(n => n * n * n)
val sum = powOf3s.reduce((prev, next) => prev + next)
PLACEHOLDERS
You can use underscores as placeholders for one or
more parameters, so long as each parameter appears
only one time within the function literal.
val numbers = List(1, 2, 3, 4)
val evens = numbers.filter(_ % 2 == 0)
val powOf3s = evens.map(n => n * n * n) // here it's necessary
val sum = powOf3s.reduce(_ + _)
ASSIGNINGFUNCTIONSTO
VALUES
val evens = (_: Int) % 2 == 0
val pow3 = (n: Int) => n * n * n
val add = (x: Int, y: Int) => x + y
val numbers = List(1, 2, 3, 4)
val result = numbers.filter(evens).map(pow3).reduce(add)
FUNCTIONSAREOBJECTS
TOO
Every function implements the FunctionN trait. The apply
method allows us to use the function syntax.
val f = new Function2[Int, Int, Int] {
def apply(y: Int, x: Int): Int = x + y
}
f(1, 2)
((x: Int, y: Int) => x + y).isInstanceOf[Function2[Int, Int, Int]]
FUNCTIONSTHATRETURN
FUNCTIONS
It's quite common to write a function that produces a
new function
def powerOf(p: Int) = (n: Int) => Math.pow(n, p).toInt
val powerOf5 = powerOf(5)
val numbers = List(1, 2, 3, 4)
numbers.map(powerOf5) //1, 32, 243, 1024
numbers.map(powerOf(2)) //1, 4, 9, 16
INNER FUNCTIONS
You can write functions inside functions
def funkyName(name: String) = {
def replaceLettersWithNumbers(s: String) = {
val numberMap = Map(
'i' -> '1', 'l' -> '1', 'e' -> '3',
'a' -> '4', 's' -> '5', 'o' -> '0')
s.map(ltr => numberMap.getOrElse(ltr, ltr))
}
replaceLettersWithNumbers(name.toLowerCase)
}
println(funkyName("Martin Odersky")) //m4rt1n 0d3r5ky
EVERYDAYEXAMPLES
The usual stuff you code almost every day.
EVERYDAYEXAMPLES
Transforming Collections from type A to B
Java:
public Collection<String> personsToNames(Collection<Person> persons) {
List<String> names = new ArrayList<String>();
for (Person p : persons) {
names.add(p.name);
}
return names;
}
EVERYDAYEXAMPLES
Transforming Collections from type A to B
Scala:
persons.map(_.name)
EVERYDAYEXAMPLES
Filter elements from Collections based on criteria
Java:
public Collection<Person> filterAges(Collection<Person> persons, int threshol
List<Person> filtered = new ArrayList<Person>();
for (Person p : persons) {
if (p.age >= threshold) {
filtered.add(p);
}
}
return filtered;
}
EVERYDAYEXAMPLES
Filter elements from Collections based on criteria
Scala:
persons.filter(_.age >= 30)
EVERYDAYEXAMPLES
Aggregation
Java:
public Integer averageAge(Collection<Person> persons) {
int ageSum = 0;
for (Person p : persons) {
ageSum += p.age;
}
return ageSum / persons.size();
}
EVERYDAYEXAMPLES
Aggregation
Scala:
persons.foldLeft(0)((sum, p) => sum + p.age) / persons.size
EVERYDAYEXAMPLES
Grouping
Java:
public Map<Integer, Collection<Person>> ageGroups(
Collection<Person> persons) {
Map<Integer, Collection<Person>> groups =
new HashMap<Integer, Collection<Person>>();
for (Person p : persons) {
if (groups.containsKey(p.age)) {
groups.get(p.age).add(p);
} else {
final ArrayList<Person> coll = new ArrayList<Person>();
coll.add(p);
groups.put(p.age, coll);
}
}
return groups;
}
EVERYDAYEXAMPLES
Grouping
Scala:
persons.groupBy(_.age)
RECURSION
Procedural way to calculate factorial
FP avoids loops with mutable state. Instead recursion is
often used.
def factorial(n: BigInt) = {
if (n == 0) 1
else {
var product: BigInt = 1
var i = n
while (i > 0) {
product *= i
i -= 1
}
product
}
}
def factorial(n: BigInt): BigInt =
if (n == 0) 1
else n * factorial(n - 1)
TAILCALLOPTIMIZATION
Previous recursive factorial consumes stack and will
throw StackOverflow for big numbers. A proper FP
language offers tail call optimization. In Scala we can use
the @tailrec annotation. The compiler will complain if it is
unable to make the function tail recursive.
def factorial(n: BigInt) = {
@tailrec def calc(n: BigInt, acc: BigInt): BigInt =
if (n == 0) acc else calc(n - 1, acc * n)
calc(n, 1)
}
FOR EXPRESSION
The for expression is a powerful tool in Scala that allows
you to:
iterate through a collection
perform nested iterations
filter out elements based on arbitrary conditions
produce new collections
FOR EXPRESSION EXAMPLE
def find(dir: File, predicate: String => Boolean): Seq[String] =
if (!dir.exists || !dir.isDirectory)
List.empty
else
for (f <- dir.listFiles if predicate(f.getName)) yield f.getName
find(new File("C:installedmaven3bin"), _.endsWith("bat"))
//ArraySeq(mvn.bat, mvnDebug.bat)
FOR EXPRESSION EXAMPLE
for (
i <- 'a' to 'c';
j <- 3 to 1 by -1
) yield (i, j)
//Vector((a,3), (a,2), (a,1), (b,3), (b,2), (b,1), (c,3), (c,2), (c,1))
IMMUTABLECOLLECTIONS
Immutability is one of the cornerstones of FP. The Scala
scala.collection.immutable package offers wide variety of
immutable collection data structures. If you really need
mutable collections then you need to use the
scala.collection.mutable package.
val nums = 1 to 10
println(nums) //Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val divBy3 = nums.filter(_ % 3 == 0)
println(divBy3) //Vector(3, 6, 9)
//nums did not change
println(nums) //Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
import scala.collection.mutable
val list = mutable.MutableList[Int](1, 2, 3)
println(list) //MutableList(1, 2, 3)
list(1) = 6
println(list) //MutableList(1, 6, 3)
LOAN PATTERN
Control abstraction pattern. The function accepts a
resource and a function. The function takes care of the
common repetitious work while borrowing the resource
to the outer function to do something interesting with it.
import java.io._
def using[A <: Closeable, B](resource: A)(op: A => B) = {
try op(resource)
finally resource.close()
}
val file = File.createTempFile("scala", "loan-pattern")
using(new FileWriter(file)) {
w => {
w.write("Can I loan some money please?")
w.flush()
}
}
val line = using(new BufferedReader(new FileReader(file))) {
r => r.readLine()
FP+OOP=FUNCTIONAL
OBJECTS
FP and OOP can be used together to produce code that is
concise, reusable and well structured. Let's implement a
simple immutable Rational number class. First in Java and
then in Scala.
JAVAIMPLEMENTATION
public final class Rational {
public final int numerator;
public final int denominator;
public Rational(final int numerator) {
this(numerator, 1);
}
public Rational(final int numerator, final int denominator) {
if (denominator == 0) {
final String msg = "Denominator must not be 0";
throw new IllegalArgumentException(msg);
}
this.numerator = numerator;
this.denominator = denominator;
}
public Rational add(final Rational that) {
final int n = this.numerator * that.denominator +
that.numerator * this.denominator;
final int d = this.denominator * that.denominator;
final int gcd = ArithmeticUtils.gcd(n, d);
return new Rational(n / gcd, d / gcd);
}
USINGTHEJAVARATIONAL
This API looks a lot like BigInteger or BigDecimal. It's
verbose. In Java can we write 1 + 1 or 3 - 2. But we can't
use + and - with Rationals. In mathematical sense
Rational is also a number. Wouldn't it be dreamy if we
could use something like:
new Rational(1).substract(new Rational(3,5)).add(new Rational(2,3));
(1 - Rational(3,5)) + Rational(2,3)
SCALAIMPLEMENTATION
final class Rational(val numerator: Int, val denominator: Int) {
if (denominator == 0)
throw new IllegalArgumentException("Denominator must not be 0")
def +(that: Rational) = {
val n = this.numerator * that.denominator +
that.numerator * this.denominator
val d = this.denominator * that.denominator
val gcd = ArithmeticUtils.gcd(n, d)
new Rational(n / gcd, d / gcd)
}
def -(that: Rational) = this + (-that)
def unary_- = new Rational(-numerator, denominator)
override def toString = numerator + "/" + denominator
}
object Rational {
def apply(numerator: Int, denominator: Int) =
new Rational(numerator, denominator)
def apply(numerator: Int) =
USINGTHESCALA
RATIONAL
import RationalConversions.int2SRational
(1 - Rational(3,5)) + Rational(2,3)
Rational(5) + 4
-Rational(8,7)
SCALAFPGUIDELINES
Don't use the var keyword. Use vals.
Don't use the while keyword. Use higher order
functions on collections or the for expression or
recursion.
Avoid the scala.collection.mutable package.
Don't use null. Use Option[T] - Some(value), None.
Scala is a powerful language. You can write code that
looks like Java. You can write code that looks like
Haskell. FP and OOP are not mutually exclusive. FP +
OOP is actually a nice combination, but try to minimize
state and mutability.
ABALANCEDATTITUDEFOR
SCALAPROGRAMMERS
“Prefer vals, immutable objects, and
methods without side effects. Reach for
them first. Use vars, mutable objects, and
methods with side effects when you have
a specific need and justification for them.”
- Programming In Scala 2nd ed
PATTERN MATCHING
PATTERN MATCHING
FEATURES
Pattern matching in Scala is basically Java switch-case on
steroids. With pattern matching we can:
Match values
Match case classes
Destructure and match collection-like structures
Destructure and match arbitrary data structures using
our own extractors
Let's look at pattern matching in more detail using
examples.
PATTERN MATCHINGON
VALUES
val turn = 1
def reallyGo = false
val result = turn match {
case 1 => "Ready"
case 2 | 3 => "Steady" //logical or
case 4 if reallyGo => "Go!" //guard
case _ => "Wut???" //catch all case
}
PATTERN MATCHINGON
CASECLASSES-AST
Abstract Syntax Tree
PATTERN MATCHINGON
CASECLASSES-AST
trait AST[T]
case class Expression[T](fn: (T, T) => T,
left: AST[T],
right: AST[T]) extends AST[T]
case class Value[T](value: T) extends AST[T]
def divide(x: Int, y: Int) = x / y
def multiply(x: Int, y: Int) = x * y
def add(x: Int, y: Int) = x + y
def subtract(x: Int, y: Int) = x - y
val ast =
Expression(divide,
Expression(add,
Expression(multiply, Value(2), Value(5)),
Expression(subtract, Value(3), Value(1))),
Value(3))
PATTERN MATCHINGON
LISTS
Most collection-like data structures in standard library
have an extractor. Extractor allows us to destruct a data
structure and match the inner elements.
val list = List("John", "Smith", 36, List("Linda", "Smith", 32))
val msg = list match {
case name :: _ :: _ :: List(spouse :: _) =>
name + " is married to " + spouse
case _ => "Cannot make sense of the list"
}
println(msg) //John is married to Linda
PATTERN MATCHINGON
EXCEPTIONS
try {
throw new NullPointerException()
} catch {
case ioEx: IOException => // do something else
case e @ (_ : NullPointerException | _: IllegalArgumentException) =>
// common logic for NPE and IAE
case unexpectedEx => // catch all case
} finally {
//clean up
}
CUSTOMEXTRACTOR
By writing our own extractor we can destruct and pattern
match other data structures in a way that makes sense in
our problem domain. For example some API returns
URLs as Strings. We can write an extractor that allows us
to destructure the URL String.
object Url {
def apply(secure: Boolean,
domain: String,
topLvlDomain: String) = {
val protocol = if (secure) "https" else "http"
protocol + "://" + domain + "." + topLvlDomain
}
def unapply(url: String) = {
def isHttp(p: String) = p.startsWith("http")
def isSecure(p: String) = p.endsWith("s")
url.split("://") match {
case Array(protocol, domainPart) if isHttp(protocol) =>
domainPart.split(".") match {
case Array(domain, topLvlDomain) =>
Some((isSecure(protocol), domain, topLvlDomain))
case _ => None
}
case _ => None
}
}
}
val msg = "https://ishisystems.com" match {
case Url(true, domain, _) =>
"Welcome to secure '%s' network".format(domain)
case url => url + " is not allowed"
}
PIMPMYLIBRARY
PIMPMYLIBRARY
In real world we are mostly dealing with 3rd party APIs.
Some APIs are well designed, some are not. We cannot
modify them to make them easier to use with our own
code. However, in Scala we can use implicit conversions
to make those 3rd party APIs more richer and expressive.
RICHDATE
java.util.Date with accessories
import java.util.{Calendar, Date}
class RichDate(val date: Date) {
def isSameDay(comparedDate: Date): Boolean = {
val cal = Calendar.getInstance()
def getYearAndDay(d: Date) = {
cal.setTime(d)
val year = cal.get(Calendar.YEAR)
val day = cal.get(Calendar.DAY_OF_YEAR)
(year, day)
}
val (y1, d1) = getYearAndDay(date)
val (y2, d2) = getYearAndDay(comparedDate)
y1 == y2 && d1 == d2
}
}
object RichDateConversions {
implicit def date2RichDate(d: Date) = new RichDate(d)
USINGRICHDATE
Now we can use java.util.Date in ways the original
authors did not think of.
import RichDateConversions.date2RichDate
val d1 = new Date
val oneHour = 60 * 60 * 1000
val d2 = new Date(d1.getTime + oneHour)
d1 isSameDay d2
DON'TOVERUSEIMPLICITS
Try to minimize the use of implicits. It makes the code
look like it's doing something magical. Implicits are even
known to confuse your IDE. If even your IDE can get
confused then a developer can definitely get confused.
SCALA&XML
SCALA&XML
Scala has good support for XML. You can:
Write XML literals
Write code inside XML literals
Query the XML with a XPath-like API
Pattern match XML
XMLLITERALS
val john =
<person>
<name>John</name>
<age>36</age>
<spouse>
<person>
<name>Linda</name>
<age>32</age>
</person>
</spouse>
</person>
CODEINSIDEXMLLITERALS
class Person(val name: String,
val age: Int,
val spouse: Option[Person]) {
def toXML: Node = xml.Utility.trim(
<person>
<name>{name}</name>
<age>{age}</age>
{if (spouse.isDefined)
<spouse>{spouse.get.toXML}</spouse>}
</person>)
override def toString: String =
"name=%s, age=%s, spouse=(%s)".format(name, age,
if(spouse.isDefined) spouse.get.toString else None)
}
val johnny = new Person("John", 36,
Some(new Person("Linda", 32, None)))
println(johnny.toXML)
val pete = new Person("Peter", 22, None)
println(pete.toXML)
SEARCHFROMXML
val john =
<person>
<name>John</name>
<age>36</age>
<spouse>
<person>
<name>Linda</name>
<age>32</age>
</person>
</spouse>
</person>
def getSpouseName(xml: Node) = {
val name = xml  "spouse"  "person"  "name"
if (name.isEmpty) None else Some(name.text)
}
println(getSpouseName(john)) //Some(Linda)
PATTERN MATCHINGON
XML
XML pattern matching is somewhat unuseful because of
the significant whitespace.
def xmlToPerson(personXML: Seq[Node]): Option[Person] = personXML match {
case <person><name>{name}</name><age>{age}</age><spouse>{person}</spouse></
Some(new Person(name.text, age.text.toInt, xmlToPerson(person)))
case <person><name>{name}</name><age>{age}</age></person> =>
Some(new Person(name.text, age.text.toInt, None))
case _ => None
}
xmlToPerson(xml.Utility.trim(personXML))
PARALLELISMAND
CONCURRENCY
PARALLELISMAND
CONCURRENCY
In Scala you can use all the tools from java.util.concurrent
in addition to some extra goodies that Scala offers:
Parallel collections
Actor library - deprecated from core Scala and moved
to Akka
PARALLELCOLLECTIONS
Most of the sequential Scala collections can be turned
into a parallel counterpart with the par function. Some
points about parallel collections:
The main use case for parallel collections is when you
need to apply a side-effect free computation to each
element of the collection and the order does not
matter.
The computation should be non-trivial to see
performance gains.
Parallel collections are implemented on top of the Java
fork-join framework.
PARALLELCOLLECTIONS
EXAMPLE
Following example calculates factorials for each element
in the collection. The numbers are quite big to make the
computation more costly.
def factorial(n: BigInt) = {
@tailrec def calc(n: BigInt, acc: BigInt): BigInt =
if (n == 0) acc else calc(n - 1, acc * n)
calc(n, 1)
}
val numbers = BigInt(100000) to BigInt(100012)
def measure(work: => Unit) {
val start = System.currentTimeMillis
work
val end = System.currentTimeMillis
println(end - start)
}
// my machine 4 cores
// 12 computations
// 12 / 4 => should get roughly 3x increase in performance
// sequential
measure(numbers.map(factorial)) // ~3 minutes
// parallel
measure(numbers.par.map(factorial)) // ~1 minute
ACTORS
The actor model represents a share-nothing message-
passing programming model that is easier to understand
for developers than shared mutable data with locks.
Actor is an object that has an inbox to receive messages.
Actor can process only one message at a time. Actors
communicate with each other by sending immutable
message objects using the ! method.
ACTOR BENEFITS
No shared data
No locks & synchronization
Asynchronous message passing
Actors can share a thread pool
Combine actors with java.util.concurrent classes. For
example, multiple actors can share a
ConcurrentHashMap
Akka offers many other benefits such as support for
distributed actors and fault tolerance, but that is
another subject
ACTOR USECASES
Simulating workflows
Distributed computing (with scatter-gather actor
design pattern)
Systems that need event driven architecture
EXAMPLE
Sprint workflow
WORKFLOW
TOPOLOGY
MESSAGES
Let's define the messages as case classes so they can be
pattern matched by actors.
case class StartSprint()
case class Develop(story: String)
case class FixBug(story: String)
case class DevelopmentDone(story: String)
case class Test(story: String)
case class TestingDone(story: String, bug: Boolean)
case class Release(story: String)
case class NewFeature(story: String)
DEVELOPER ACTOR
class Developer(val name: String) extends Actor {
def receive = {
case Develop(story) => develop(story)
case FixBug(story) => fixBug(story)
}
def develop(story: String) {
println(name + " develops " + story)
tracker ! DevelopmentDone(story)
}
def fixBug(story: String) {
println(name + " fixes bug in " + story)
tracker ! DevelopmentDone(story)
}
}
TESTER ACTOR
class Tester(val name: String) extends Actor {
def receive = {
case Test(story) => test(story)
}
def test(story: String) {
val foundBug = Random.nextBoolean()
val log =
if (foundBug) name + " found a bug in " + story
else name + " verified that " + story + " works"
println(log)
tracker ! TestingDone(story, foundBug)
}
}
RELEASEMANAGER ACTOR
class RM extends Actor {
def receive = {
case Release(story) => {
println("RM deployed " + story + " to production")
client ! NewFeature(story)
}
}
}
CLIENTACTOR
class Client extends Actor {
def receive = {
case NewFeature(feature) => {
println("Client tries out " + feature +
" and is satisfied with it")
}
}
}
TRACKER ACTOR
As seen from the diagrams the Tracker actor coordinates
the work between developers, testers and the release
manager.
class Tracker(stories: Seq[String]) extends Actor {
/**
* Map of Story -> (Dev, Tester)
* Each story gets assigned a developer and a tester.
*/
val sprintPlan = {
val numberOfStories = stories.size
def repeat[T](resources: Seq[T]) =
Stream.continually(resources).flatten.take(numberOfStories)
val assignments =
(stories, repeat(developers), repeat(testers)).zipped.toList
assignments.map {
case (story, dev, tester) => (story, (dev, tester))
}.toMap
}
APPCONTEXT
Container that creates the actor system.
object AppContext {
println("Setting up AppContext...")
val actorContext = ActorSystem("SprintAppActors")
val tracker = {
val stories = for (i <- 1 to 10) yield "Feature-" + i
toActor(new Tracker(stories), "tracker")
}
val developers = toActors(List("Rasmeet", "Viral", "Dhruv"),
(name: String) => new Developer(name), "developers")
val testers = toActors(List("Dilip", "Shaishav"),
(name: String) => new Tester(name), "testers")
val val releaseManager = toActor(new RM, "RM")
val client = toActor(new Client, "Client")
def toActors[T](xs: Seq[T], fn: T => Actor, groupName: String) =
xs.zipWithIndex.map {
case (x, i) => toActor(fn(x), groupName + "-" + i)
LAUNCHTHEAPP
import AppContext._
object Simulation {
def main(args: Array[String]) {
tracker ! StartSprint
}
}
SAMPLEOUTPUT
Setting up AppContext...
Starting sprint
Rasmeet develops Feature-10
Viral develops Feature-5
Dhruv develops Feature-6
Dhruv develops Feature-9
Dhruv develops Feature-3
Rasmeet develops Feature-1
Viral develops Feature-2
Rasmeet develops Feature-7
Viral develops Feature-8
Rasmeet develops Feature-4
Shaishav found a bug in Feature-5
Dilip verified that Feature-6 works
Shaishav verified that Feature-2 works
Shaishav verified that Feature-8 works
Dilip found a bug in Feature-10
Dilip verified that Feature-9 works
Dilip found a bug in Feature-3
Dilip found a bug in Feature-1
Dilip verified that Feature-7 works
Dilip found a bug in Feature-4
Viral fixes bug in Feature-5
RM deployed Feature-6 to production
Rasmeet fixes bug in Feature-10
Rasmeet fixes bug in Feature-1
SCALAIN REALWORLD
OBSERVATIONS
IDE. Intellij is currently hands down the best IDE for
Scala. Eclipse Scala plugin is coming along but still has
too many bugs and quirks to make it worthwile. Also,
Eclipse in general has been getting slower with each
successive release.
OBSERVATIONS
Code is really concise. Passing functions to other
functions is awesome. I really do feel encouraged to write
immutable classes and avoid changing state as Scala
makes it easy to write without ceremony. The downside
is that developers can write too concise code that
becomes hard to read. Best advice is to try to keep the
code simple even if it means writing a bit more code.
OBSERVATIONS
It's easy to interop with existing Java code. However, it's
not so easy to call some of the Scala code from Java.
OBSERVATIONS
Scala method definitions can be hard to understand.
// Wut me supposed to do wit it???
scan[B >: A, That](z: B)(op: (B, B) ? B)(implicit cbf: CanBuildFrom[List[A],
// Huh?
:+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Repr, B, That]): That
OBSERVATIONS
When the team uses Scala code reviews become very
important. People with different programming
backgrounds will use Scala differently. Haskell guys will
write it as if it were Haskell. Java guys will write it as if it
were Java. In general it's better to lean towards FP
principles as it tends to produce code that is more
reusable and is easier to understand in isolation.
OBSERVATIONS
Scala really shines when it comes to mixing OOP with FP,
but it's not a good language to learn FP. You will benefit a
lot if you get your hands dirty with Haskell or Clojure and
then come back to Scala with a new perspective.
SCALAADOPTION
STRATEGY
Decide as a team whether you want to use Scala. This
is key.
Start by writing test cases in Scala. You will be only
using basic vanilla Scala, but at least it will give you
confidence that you can effectively use Scala together
with the existing code base.
If you're introducing a new backend component or
breaking up an existing monolithic component give
Scala a chance.
LEARNINGMATERIALS
Free online Scala course on Coursera
Programming In Scala 2nd ed
Scala in Depth
Functional Programming in Scala
Twitter's Scala School
Official documentation
Akka documentation
Scala Days 2013 videos
InfoQ Scala presentations
99 Scala problems
THANKYOU

Weitere ähnliche Inhalte

Was ist angesagt?

Chap 3php array part 3
Chap 3php array part 3Chap 3php array part 3
Chap 3php array part 3monikadeshmane
 
The underestimated power of KeyPaths
The underestimated power of KeyPathsThe underestimated power of KeyPaths
The underestimated power of KeyPathsVincent Pradeilles
 
Probabilistic Programming in Scala
Probabilistic Programming in ScalaProbabilistic Programming in Scala
Probabilistic Programming in ScalaBeScala
 
Template Haskell とか
Template Haskell とかTemplate Haskell とか
Template Haskell とかHiromi Ishii
 
Fun never stops. introduction to haskell programming language
Fun never stops. introduction to haskell programming languageFun never stops. introduction to haskell programming language
Fun never stops. introduction to haskell programming languagePawel Szulc
 
Functional Programming In Java
Functional Programming In JavaFunctional Programming In Java
Functional Programming In JavaAndrei Solntsev
 
CoffeeScript
CoffeeScriptCoffeeScript
CoffeeScriptNone
 
Introduction to Python
Introduction to PythonIntroduction to Python
Introduction to PythonUC San Diego
 
Is Haskell an acceptable Perl?
Is Haskell an acceptable Perl?Is Haskell an acceptable Perl?
Is Haskell an acceptable Perl?osfameron
 
Unit 1-array,lists and hashes
Unit 1-array,lists and hashesUnit 1-array,lists and hashes
Unit 1-array,lists and hashessana mateen
 
Tuga it 2016 - What's New In C# 6
Tuga it 2016 - What's New In C# 6Tuga it 2016 - What's New In C# 6
Tuga it 2016 - What's New In C# 6Paulo Morgado
 
First few months with Kotlin - Introduction through android examples
First few months with Kotlin - Introduction through android examplesFirst few months with Kotlin - Introduction through android examples
First few months with Kotlin - Introduction through android examplesNebojša Vukšić
 
Class 5 - PHP Strings
Class 5 - PHP StringsClass 5 - PHP Strings
Class 5 - PHP StringsAhmed Swilam
 
From Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risksFrom Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risksSeniorDevOnly
 
Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)Calvin Cheng
 

Was ist angesagt? (20)

Chap 3php array part 3
Chap 3php array part 3Chap 3php array part 3
Chap 3php array part 3
 
Coffee Script
Coffee ScriptCoffee Script
Coffee Script
 
1 the ruby way
1   the ruby way1   the ruby way
1 the ruby way
 
The underestimated power of KeyPaths
The underestimated power of KeyPathsThe underestimated power of KeyPaths
The underestimated power of KeyPaths
 
Probabilistic Programming in Scala
Probabilistic Programming in ScalaProbabilistic Programming in Scala
Probabilistic Programming in Scala
 
Template Haskell とか
Template Haskell とかTemplate Haskell とか
Template Haskell とか
 
Fun never stops. introduction to haskell programming language
Fun never stops. introduction to haskell programming languageFun never stops. introduction to haskell programming language
Fun never stops. introduction to haskell programming language
 
Functional programming in java
Functional programming in javaFunctional programming in java
Functional programming in java
 
Functional Programming In Java
Functional Programming In JavaFunctional Programming In Java
Functional Programming In Java
 
CoffeeScript
CoffeeScriptCoffeeScript
CoffeeScript
 
Introduction to Python
Introduction to PythonIntroduction to Python
Introduction to Python
 
Fun with Kotlin
Fun with KotlinFun with Kotlin
Fun with Kotlin
 
Is Haskell an acceptable Perl?
Is Haskell an acceptable Perl?Is Haskell an acceptable Perl?
Is Haskell an acceptable Perl?
 
Unit 1-array,lists and hashes
Unit 1-array,lists and hashesUnit 1-array,lists and hashes
Unit 1-array,lists and hashes
 
Tuga it 2016 - What's New In C# 6
Tuga it 2016 - What's New In C# 6Tuga it 2016 - What's New In C# 6
Tuga it 2016 - What's New In C# 6
 
First few months with Kotlin - Introduction through android examples
First few months with Kotlin - Introduction through android examplesFirst few months with Kotlin - Introduction through android examples
First few months with Kotlin - Introduction through android examples
 
Class 5 - PHP Strings
Class 5 - PHP StringsClass 5 - PHP Strings
Class 5 - PHP Strings
 
From Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risksFrom Java to Scala - advantages and possible risks
From Java to Scala - advantages and possible risks
 
Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)Functional Programming for OO Programmers (part 2)
Functional Programming for OO Programmers (part 2)
 
Scala in practice
Scala in practiceScala in practice
Scala in practice
 

Andere mochten auch

Presentation from Dusseldorf-Germany
Presentation from Dusseldorf-GermanyPresentation from Dusseldorf-Germany
Presentation from Dusseldorf-GermanyMoAlfonsel
 
Ha autobiography
Ha autobiographyHa autobiography
Ha autobiographylha2013
 
Universal Design
Universal DesignUniversal Design
Universal Designparkws3
 
Storyboard pres1
Storyboard pres1Storyboard pres1
Storyboard pres1nikievan1
 
Content is King
Content is KingContent is King
Content is KingAIRR Media
 
Harnessing the power of content marketing final
Harnessing the power of content marketing finalHarnessing the power of content marketing final
Harnessing the power of content marketing finalsdgeorge3
 
Mgt448 lt a_week5 Copyright 2013 Edward F. T. Charfauros. Reference, www.Your...
Mgt448 lt a_week5 Copyright 2013 Edward F. T. Charfauros. Reference, www.Your...Mgt448 lt a_week5 Copyright 2013 Edward F. T. Charfauros. Reference, www.Your...
Mgt448 lt a_week5 Copyright 2013 Edward F. T. Charfauros. Reference, www.Your...Edward F. T. Charfauros
 
المرجع الأساسي للذاكرة د. جاري سمول
المرجع الأساسي للذاكرة   د. جاري سمولالمرجع الأساسي للذاكرة   د. جاري سمول
المرجع الأساسي للذاكرة د. جاري سمولlhassandanguou
 
อาชญากรรมทางคอมพิวเตอร์
อาชญากรรมทางคอมพิวเตอร์อาชญากรรมทางคอมพิวเตอร์
อาชญากรรมทางคอมพิวเตอร์Tom-Eve Jutamat
 
Sorento Restaurant serves Italian & Mediterranean food at Toronto-which satis...
Sorento Restaurant serves Italian & Mediterranean food at Toronto-which satis...Sorento Restaurant serves Italian & Mediterranean food at Toronto-which satis...
Sorento Restaurant serves Italian & Mediterranean food at Toronto-which satis...Sorento Restaurant
 
Δραστηριοτητα 1/ ΕΔΜ51/ ΑΠΚΥ
Δραστηριοτητα 1/ ΕΔΜ51/ ΑΠΚΥΔραστηριοτητα 1/ ΕΔΜ51/ ΑΠΚΥ
Δραστηριοτητα 1/ ΕΔΜ51/ ΑΠΚΥElena Stavrinidou
 

Andere mochten auch (20)

Tutorial
TutorialTutorial
Tutorial
 
Presentation from Dusseldorf-Germany
Presentation from Dusseldorf-GermanyPresentation from Dusseldorf-Germany
Presentation from Dusseldorf-Germany
 
Ha autobiography
Ha autobiographyHa autobiography
Ha autobiography
 
Universal Design
Universal DesignUniversal Design
Universal Design
 
Storyboard pres1
Storyboard pres1Storyboard pres1
Storyboard pres1
 
Content is King
Content is KingContent is King
Content is King
 
Harnessing the power of content marketing final
Harnessing the power of content marketing finalHarnessing the power of content marketing final
Harnessing the power of content marketing final
 
Filming 1
Filming 1Filming 1
Filming 1
 
Mgt448 lt a_week5 Copyright 2013 Edward F. T. Charfauros. Reference, www.Your...
Mgt448 lt a_week5 Copyright 2013 Edward F. T. Charfauros. Reference, www.Your...Mgt448 lt a_week5 Copyright 2013 Edward F. T. Charfauros. Reference, www.Your...
Mgt448 lt a_week5 Copyright 2013 Edward F. T. Charfauros. Reference, www.Your...
 
Quick start guide 508
Quick start guide 508Quick start guide 508
Quick start guide 508
 
المرجع الأساسي للذاكرة د. جاري سمول
المرجع الأساسي للذاكرة   د. جاري سمولالمرجع الأساسي للذاكرة   د. جاري سمول
المرجع الأساسي للذاكرة د. جاري سمول
 
อาชญากรรมทางคอมพิวเตอร์
อาชญากรรมทางคอมพิวเตอร์อาชญากรรมทางคอมพิวเตอร์
อาชญากรรมทางคอมพิวเตอร์
 
Un padre nuestro
Un padre nuestroUn padre nuestro
Un padre nuestro
 
Task 1 page layout
Task 1  page layoutTask 1  page layout
Task 1 page layout
 
diapositivas
diapositivasdiapositivas
diapositivas
 
InTouch Demo
InTouch DemoInTouch Demo
InTouch Demo
 
Chapter 3
Chapter 3Chapter 3
Chapter 3
 
Md bro eng
Md bro engMd bro eng
Md bro eng
 
Sorento Restaurant serves Italian & Mediterranean food at Toronto-which satis...
Sorento Restaurant serves Italian & Mediterranean food at Toronto-which satis...Sorento Restaurant serves Italian & Mediterranean food at Toronto-which satis...
Sorento Restaurant serves Italian & Mediterranean food at Toronto-which satis...
 
Δραστηριοτητα 1/ ΕΔΜ51/ ΑΠΚΥ
Δραστηριοτητα 1/ ΕΔΜ51/ ΑΠΚΥΔραστηριοτητα 1/ ΕΔΜ51/ ΑΠΚΥ
Δραστηριοτητα 1/ ΕΔΜ51/ ΑΠΚΥ
 

Ähnlich wie Introduction To Scala

pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
Intro to scala
Intro to scalaIntro to scala
Intro to scalaJoe Zulli
 
An Introduction to Scala (2014)
An Introduction to Scala (2014)An Introduction to Scala (2014)
An Introduction to Scala (2014)William Narmontas
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойSigma Software
 
The Death of Final Tagless
The Death of Final TaglessThe Death of Final Tagless
The Death of Final TaglessJohn De Goes
 
Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Jesper Kamstrup Linnet
 
Introduction to Scala for JCConf Taiwan
Introduction to Scala for JCConf TaiwanIntroduction to Scala for JCConf Taiwan
Introduction to Scala for JCConf TaiwanJimin Hsieh
 
Scala Quick Introduction
Scala Quick IntroductionScala Quick Introduction
Scala Quick IntroductionDamian Jureczko
 
Scala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar ProkopecScala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar ProkopecLoïc Descotte
 

Ähnlich wie Introduction To Scala (20)

pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
Intro to scala
Intro to scalaIntro to scala
Intro to scala
 
A bit about Scala
A bit about ScalaA bit about Scala
A bit about Scala
 
An Introduction to Scala (2014)
An Introduction to Scala (2014)An Introduction to Scala (2014)
An Introduction to Scala (2014)
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай Мозговой
 
What's New In C# 7
What's New In C# 7What's New In C# 7
What's New In C# 7
 
Scala in Practice
Scala in PracticeScala in Practice
Scala in Practice
 
The Death of Final Tagless
The Death of Final TaglessThe Death of Final Tagless
The Death of Final Tagless
 
Scala ntnu
Scala ntnuScala ntnu
Scala ntnu
 
Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?Scala - en bedre og mere effektiv Java?
Scala - en bedre og mere effektiv Java?
 
Introduction to Scala for JCConf Taiwan
Introduction to Scala for JCConf TaiwanIntroduction to Scala for JCConf Taiwan
Introduction to Scala for JCConf Taiwan
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
Scala for curious
Scala for curiousScala for curious
Scala for curious
 
Scala Quick Introduction
Scala Quick IntroductionScala Quick Introduction
Scala Quick Introduction
 
Scala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar ProkopecScala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar Prokopec
 

Kürzlich hochgeladen

GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 

Kürzlich hochgeladen (20)

GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 

Introduction To Scala

  • 2. TOPICS JVM languages landscape OOP FP Pattern matching Pimp my library XML Parallel collections Actors Scala in real world
  • 4.
  • 5. JAVAPROSANDCONS Pros Simple language Portable Lot's of libraries and frameworks Big community Cons Class based OOP is used for everything, even when inappropriate, due to lack of support for anything else Lot's of boilerplate code Favors mutability
  • 6. WHYTRYOTHER JVM LANGUAGES? Those languages tend to be more expressive - say more, write less Discover new ways of thinking about problems Use the existing Java libraries/frameworks to fill in the gaps
  • 8. OVERVIEW Created by Martin Odersky Appeared around 2003 Statically typed Type inference Mixture of OOP and FP Actor concurrency Very good Java interop Currently the most widely adopted alternate JVM language
  • 10. PERSON IN JAVA import static java.lang.String.format; public class Person { public final String name; public final int age; public Person(final String name, final int age) { this.name = name; this.age = age; } public String greet() { return format("Hello, my name is %s", name); } public String greet(final Person person) { return format("Hello, %s, my name is %s", person.name, name); } @Override public String toString() { return format("name=%s, age=%d", name, age); } }
  • 11. SAMEPERSON IN SCALA class Person(val name: String, val age: Int) { def greet = "Hello, my name is %s".format(name) def greet(person: Person) = "Hello, %s, my name is %s".format(person.name, name) override def toString = "name=%s, age=%d".format(name, age) }
  • 12. JOE,MEETJOE val joe = new Person("Joe", 35) val age = joe.age val olderJoe = new Person(joe.name, age + 1) joe.greet(olderJoe) joe greet olderJoe
  • 13. TYPEINFERENCE Scala code looks a bit like scripting language, right? That is because Scala compiler can sometimes infer the types. In that case you don't need to declare types explicitly. But you can, if you want. val joe = new Person("Joe", 35) val age = joe.age
  • 14. WITHEXPLICITTYPES val joe: Person = new Person("Joe", 35) val age: Int = joe.age val olderJoe: Person = new Person(joe.name, age + 1) joe greet olderJoe def makeFriends(p1: Person, p2: Person): String = "%s and %s became good friends".format(p1.name, p2.name) makeFriends(joe, olderJoe)
  • 15. INHERITANCE abstract class A { def call = "A" } trait B { def call = "B" } trait C { def call = "C" } class ABC extends A with B with C { override def call = super.call } val abc = new ABC println(abc.call) //prints C
  • 16. ANONYMOUSCLASSES trait Jedi { def useForceOn(p: Person): String def greet(p: Person) = "May the force be with you, %s!".format(p.name) } trait ForceLightning { def useForceOn(p: Person) = "%s gets shocked with force lightning" } val obiWan = new Person("Obi Wan", 71) with Jedi { override def greet(p: Person) = super.greet(p) def useForceOn(p: Person): String = "These are not the droids you're looking for, %s".format(p.name) } val anakin = new Person("Anakin", 27) with Jedi with ForceLightning { override def greet(p: Person) = "Join the dark side, %s!".format(p.name) }
  • 17. GENERICS class Pair[A,B](val first: A, val second: B) { def add[C](third: C) = new Triple(first, second, third) } class Triple[A,B,C](val first: A, val second: B, val third: C) val p = new Pair("Joe", 36) val t = p.add('MALE)
  • 18. COMPANION OBJECT class Pair[A, B](val first: A, val second: B) object Pair { def apply[A, B](first: A, second: B) = new Pair(first, second) def empty[A, B] = new Pair[Option[A], Option[B]](None, None) } //Pair[String, Int] val p1 = Pair("Joe", 36) //Pair[Option[String], Option[Int]] val p2 = Pair.empty[String, Int]
  • 20. FP Using side effect free functions for computations Avoiding mutable data structures and variables First-class functions Recursion
  • 21. FPBENEFITS Side effect free functions are easy to test and understand. Functions are more reusable than classes Makes concurrency and parallelism easier More declarative and concise code Stop worrying what objects got mutated between method calls and instead start combining functions to transform the input to the desired output
  • 22. OOP+FP OOP generally is about nouns (Person, Car, Record) FP is about verbs (filter, map, reduce, group, zip) OOP offers a way to structure FP offers a way to compute In large projects we benefit from both
  • 23. FPUSECASES Good fit: Transforming data Systems where you need concurrency and parallelism Not a good fit: UI (although, rumor has it that FRP makes UI programming easy) IO (read/write file, query the DB, make a HTTP request) PS! Above scenarios are all good fit for Scala as you can easily change programming paradigms
  • 25. FUNCTIONSAS PARAMETERS filter, map and reduce are functions defined on the List object filter expects a function of A => Boolean map expects a function of A => B reduce expects a function of (A, A) => A def isEven(x: Int) = x % 2 == 0 def pow3(x: Int) = x * x * x def add(x: Int, y: Int) = x + y val numbers = List(1, 2, 3, 4) numbers.filter(isEven).map(pow3).reduce(add) //72
  • 26. FUNCTION LITERALS All FP languages support function literals since it's the central part of the paradigm val numbers = List(1, 2, 3, 4) val evens = numbers.filter(n => n % 2 == 0) val powOf3s = evens.map(n => n * n * n) val sum = powOf3s.reduce((prev, next) => prev + next)
  • 27. PLACEHOLDERS You can use underscores as placeholders for one or more parameters, so long as each parameter appears only one time within the function literal. val numbers = List(1, 2, 3, 4) val evens = numbers.filter(_ % 2 == 0) val powOf3s = evens.map(n => n * n * n) // here it's necessary val sum = powOf3s.reduce(_ + _)
  • 28. ASSIGNINGFUNCTIONSTO VALUES val evens = (_: Int) % 2 == 0 val pow3 = (n: Int) => n * n * n val add = (x: Int, y: Int) => x + y val numbers = List(1, 2, 3, 4) val result = numbers.filter(evens).map(pow3).reduce(add)
  • 29. FUNCTIONSAREOBJECTS TOO Every function implements the FunctionN trait. The apply method allows us to use the function syntax. val f = new Function2[Int, Int, Int] { def apply(y: Int, x: Int): Int = x + y } f(1, 2) ((x: Int, y: Int) => x + y).isInstanceOf[Function2[Int, Int, Int]]
  • 30. FUNCTIONSTHATRETURN FUNCTIONS It's quite common to write a function that produces a new function def powerOf(p: Int) = (n: Int) => Math.pow(n, p).toInt val powerOf5 = powerOf(5) val numbers = List(1, 2, 3, 4) numbers.map(powerOf5) //1, 32, 243, 1024 numbers.map(powerOf(2)) //1, 4, 9, 16
  • 31. INNER FUNCTIONS You can write functions inside functions def funkyName(name: String) = { def replaceLettersWithNumbers(s: String) = { val numberMap = Map( 'i' -> '1', 'l' -> '1', 'e' -> '3', 'a' -> '4', 's' -> '5', 'o' -> '0') s.map(ltr => numberMap.getOrElse(ltr, ltr)) } replaceLettersWithNumbers(name.toLowerCase) } println(funkyName("Martin Odersky")) //m4rt1n 0d3r5ky
  • 32. EVERYDAYEXAMPLES The usual stuff you code almost every day.
  • 33. EVERYDAYEXAMPLES Transforming Collections from type A to B Java: public Collection<String> personsToNames(Collection<Person> persons) { List<String> names = new ArrayList<String>(); for (Person p : persons) { names.add(p.name); } return names; }
  • 34. EVERYDAYEXAMPLES Transforming Collections from type A to B Scala: persons.map(_.name)
  • 35. EVERYDAYEXAMPLES Filter elements from Collections based on criteria Java: public Collection<Person> filterAges(Collection<Person> persons, int threshol List<Person> filtered = new ArrayList<Person>(); for (Person p : persons) { if (p.age >= threshold) { filtered.add(p); } } return filtered; }
  • 36. EVERYDAYEXAMPLES Filter elements from Collections based on criteria Scala: persons.filter(_.age >= 30)
  • 37. EVERYDAYEXAMPLES Aggregation Java: public Integer averageAge(Collection<Person> persons) { int ageSum = 0; for (Person p : persons) { ageSum += p.age; } return ageSum / persons.size(); }
  • 39. EVERYDAYEXAMPLES Grouping Java: public Map<Integer, Collection<Person>> ageGroups( Collection<Person> persons) { Map<Integer, Collection<Person>> groups = new HashMap<Integer, Collection<Person>>(); for (Person p : persons) { if (groups.containsKey(p.age)) { groups.get(p.age).add(p); } else { final ArrayList<Person> coll = new ArrayList<Person>(); coll.add(p); groups.put(p.age, coll); } } return groups; }
  • 41. RECURSION Procedural way to calculate factorial FP avoids loops with mutable state. Instead recursion is often used. def factorial(n: BigInt) = { if (n == 0) 1 else { var product: BigInt = 1 var i = n while (i > 0) { product *= i i -= 1 } product } } def factorial(n: BigInt): BigInt = if (n == 0) 1 else n * factorial(n - 1)
  • 42. TAILCALLOPTIMIZATION Previous recursive factorial consumes stack and will throw StackOverflow for big numbers. A proper FP language offers tail call optimization. In Scala we can use the @tailrec annotation. The compiler will complain if it is unable to make the function tail recursive. def factorial(n: BigInt) = { @tailrec def calc(n: BigInt, acc: BigInt): BigInt = if (n == 0) acc else calc(n - 1, acc * n) calc(n, 1) }
  • 43. FOR EXPRESSION The for expression is a powerful tool in Scala that allows you to: iterate through a collection perform nested iterations filter out elements based on arbitrary conditions produce new collections
  • 44. FOR EXPRESSION EXAMPLE def find(dir: File, predicate: String => Boolean): Seq[String] = if (!dir.exists || !dir.isDirectory) List.empty else for (f <- dir.listFiles if predicate(f.getName)) yield f.getName find(new File("C:installedmaven3bin"), _.endsWith("bat")) //ArraySeq(mvn.bat, mvnDebug.bat)
  • 45. FOR EXPRESSION EXAMPLE for ( i <- 'a' to 'c'; j <- 3 to 1 by -1 ) yield (i, j) //Vector((a,3), (a,2), (a,1), (b,3), (b,2), (b,1), (c,3), (c,2), (c,1))
  • 46. IMMUTABLECOLLECTIONS Immutability is one of the cornerstones of FP. The Scala scala.collection.immutable package offers wide variety of immutable collection data structures. If you really need mutable collections then you need to use the scala.collection.mutable package.
  • 47. val nums = 1 to 10 println(nums) //Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) val divBy3 = nums.filter(_ % 3 == 0) println(divBy3) //Vector(3, 6, 9) //nums did not change println(nums) //Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) import scala.collection.mutable val list = mutable.MutableList[Int](1, 2, 3) println(list) //MutableList(1, 2, 3) list(1) = 6 println(list) //MutableList(1, 6, 3)
  • 48. LOAN PATTERN Control abstraction pattern. The function accepts a resource and a function. The function takes care of the common repetitious work while borrowing the resource to the outer function to do something interesting with it. import java.io._ def using[A <: Closeable, B](resource: A)(op: A => B) = { try op(resource) finally resource.close() } val file = File.createTempFile("scala", "loan-pattern") using(new FileWriter(file)) { w => { w.write("Can I loan some money please?") w.flush() } } val line = using(new BufferedReader(new FileReader(file))) { r => r.readLine()
  • 49.
  • 50. FP+OOP=FUNCTIONAL OBJECTS FP and OOP can be used together to produce code that is concise, reusable and well structured. Let's implement a simple immutable Rational number class. First in Java and then in Scala.
  • 51. JAVAIMPLEMENTATION public final class Rational { public final int numerator; public final int denominator; public Rational(final int numerator) { this(numerator, 1); } public Rational(final int numerator, final int denominator) { if (denominator == 0) { final String msg = "Denominator must not be 0"; throw new IllegalArgumentException(msg); } this.numerator = numerator; this.denominator = denominator; } public Rational add(final Rational that) { final int n = this.numerator * that.denominator + that.numerator * this.denominator; final int d = this.denominator * that.denominator; final int gcd = ArithmeticUtils.gcd(n, d); return new Rational(n / gcd, d / gcd); }
  • 52. USINGTHEJAVARATIONAL This API looks a lot like BigInteger or BigDecimal. It's verbose. In Java can we write 1 + 1 or 3 - 2. But we can't use + and - with Rationals. In mathematical sense Rational is also a number. Wouldn't it be dreamy if we could use something like: new Rational(1).substract(new Rational(3,5)).add(new Rational(2,3)); (1 - Rational(3,5)) + Rational(2,3)
  • 53. SCALAIMPLEMENTATION final class Rational(val numerator: Int, val denominator: Int) { if (denominator == 0) throw new IllegalArgumentException("Denominator must not be 0") def +(that: Rational) = { val n = this.numerator * that.denominator + that.numerator * this.denominator val d = this.denominator * that.denominator val gcd = ArithmeticUtils.gcd(n, d) new Rational(n / gcd, d / gcd) } def -(that: Rational) = this + (-that) def unary_- = new Rational(-numerator, denominator) override def toString = numerator + "/" + denominator } object Rational { def apply(numerator: Int, denominator: Int) = new Rational(numerator, denominator) def apply(numerator: Int) =
  • 54. USINGTHESCALA RATIONAL import RationalConversions.int2SRational (1 - Rational(3,5)) + Rational(2,3) Rational(5) + 4 -Rational(8,7)
  • 55. SCALAFPGUIDELINES Don't use the var keyword. Use vals. Don't use the while keyword. Use higher order functions on collections or the for expression or recursion. Avoid the scala.collection.mutable package. Don't use null. Use Option[T] - Some(value), None. Scala is a powerful language. You can write code that looks like Java. You can write code that looks like Haskell. FP and OOP are not mutually exclusive. FP + OOP is actually a nice combination, but try to minimize state and mutability.
  • 56. ABALANCEDATTITUDEFOR SCALAPROGRAMMERS “Prefer vals, immutable objects, and methods without side effects. Reach for them first. Use vars, mutable objects, and methods with side effects when you have a specific need and justification for them.” - Programming In Scala 2nd ed
  • 58. PATTERN MATCHING FEATURES Pattern matching in Scala is basically Java switch-case on steroids. With pattern matching we can: Match values Match case classes Destructure and match collection-like structures Destructure and match arbitrary data structures using our own extractors Let's look at pattern matching in more detail using examples.
  • 59. PATTERN MATCHINGON VALUES val turn = 1 def reallyGo = false val result = turn match { case 1 => "Ready" case 2 | 3 => "Steady" //logical or case 4 if reallyGo => "Go!" //guard case _ => "Wut???" //catch all case }
  • 61. PATTERN MATCHINGON CASECLASSES-AST trait AST[T] case class Expression[T](fn: (T, T) => T, left: AST[T], right: AST[T]) extends AST[T] case class Value[T](value: T) extends AST[T] def divide(x: Int, y: Int) = x / y def multiply(x: Int, y: Int) = x * y def add(x: Int, y: Int) = x + y def subtract(x: Int, y: Int) = x - y val ast = Expression(divide, Expression(add, Expression(multiply, Value(2), Value(5)), Expression(subtract, Value(3), Value(1))), Value(3))
  • 62. PATTERN MATCHINGON LISTS Most collection-like data structures in standard library have an extractor. Extractor allows us to destruct a data structure and match the inner elements. val list = List("John", "Smith", 36, List("Linda", "Smith", 32)) val msg = list match { case name :: _ :: _ :: List(spouse :: _) => name + " is married to " + spouse case _ => "Cannot make sense of the list" } println(msg) //John is married to Linda
  • 63. PATTERN MATCHINGON EXCEPTIONS try { throw new NullPointerException() } catch { case ioEx: IOException => // do something else case e @ (_ : NullPointerException | _: IllegalArgumentException) => // common logic for NPE and IAE case unexpectedEx => // catch all case } finally { //clean up }
  • 64. CUSTOMEXTRACTOR By writing our own extractor we can destruct and pattern match other data structures in a way that makes sense in our problem domain. For example some API returns URLs as Strings. We can write an extractor that allows us to destructure the URL String.
  • 65. object Url { def apply(secure: Boolean, domain: String, topLvlDomain: String) = { val protocol = if (secure) "https" else "http" protocol + "://" + domain + "." + topLvlDomain } def unapply(url: String) = { def isHttp(p: String) = p.startsWith("http") def isSecure(p: String) = p.endsWith("s") url.split("://") match { case Array(protocol, domainPart) if isHttp(protocol) => domainPart.split(".") match { case Array(domain, topLvlDomain) => Some((isSecure(protocol), domain, topLvlDomain)) case _ => None } case _ => None } } } val msg = "https://ishisystems.com" match { case Url(true, domain, _) => "Welcome to secure '%s' network".format(domain) case url => url + " is not allowed" }
  • 67. PIMPMYLIBRARY In real world we are mostly dealing with 3rd party APIs. Some APIs are well designed, some are not. We cannot modify them to make them easier to use with our own code. However, in Scala we can use implicit conversions to make those 3rd party APIs more richer and expressive.
  • 68. RICHDATE java.util.Date with accessories import java.util.{Calendar, Date} class RichDate(val date: Date) { def isSameDay(comparedDate: Date): Boolean = { val cal = Calendar.getInstance() def getYearAndDay(d: Date) = { cal.setTime(d) val year = cal.get(Calendar.YEAR) val day = cal.get(Calendar.DAY_OF_YEAR) (year, day) } val (y1, d1) = getYearAndDay(date) val (y2, d2) = getYearAndDay(comparedDate) y1 == y2 && d1 == d2 } } object RichDateConversions { implicit def date2RichDate(d: Date) = new RichDate(d)
  • 69. USINGRICHDATE Now we can use java.util.Date in ways the original authors did not think of. import RichDateConversions.date2RichDate val d1 = new Date val oneHour = 60 * 60 * 1000 val d2 = new Date(d1.getTime + oneHour) d1 isSameDay d2
  • 70. DON'TOVERUSEIMPLICITS Try to minimize the use of implicits. It makes the code look like it's doing something magical. Implicits are even known to confuse your IDE. If even your IDE can get confused then a developer can definitely get confused.
  • 72. SCALA&XML Scala has good support for XML. You can: Write XML literals Write code inside XML literals Query the XML with a XPath-like API Pattern match XML
  • 74. CODEINSIDEXMLLITERALS class Person(val name: String, val age: Int, val spouse: Option[Person]) { def toXML: Node = xml.Utility.trim( <person> <name>{name}</name> <age>{age}</age> {if (spouse.isDefined) <spouse>{spouse.get.toXML}</spouse>} </person>) override def toString: String = "name=%s, age=%s, spouse=(%s)".format(name, age, if(spouse.isDefined) spouse.get.toString else None) } val johnny = new Person("John", 36, Some(new Person("Linda", 32, None))) println(johnny.toXML) val pete = new Person("Peter", 22, None) println(pete.toXML)
  • 75. SEARCHFROMXML val john = <person> <name>John</name> <age>36</age> <spouse> <person> <name>Linda</name> <age>32</age> </person> </spouse> </person> def getSpouseName(xml: Node) = { val name = xml "spouse" "person" "name" if (name.isEmpty) None else Some(name.text) } println(getSpouseName(john)) //Some(Linda)
  • 76. PATTERN MATCHINGON XML XML pattern matching is somewhat unuseful because of the significant whitespace. def xmlToPerson(personXML: Seq[Node]): Option[Person] = personXML match { case <person><name>{name}</name><age>{age}</age><spouse>{person}</spouse></ Some(new Person(name.text, age.text.toInt, xmlToPerson(person))) case <person><name>{name}</name><age>{age}</age></person> => Some(new Person(name.text, age.text.toInt, None)) case _ => None } xmlToPerson(xml.Utility.trim(personXML))
  • 78. PARALLELISMAND CONCURRENCY In Scala you can use all the tools from java.util.concurrent in addition to some extra goodies that Scala offers: Parallel collections Actor library - deprecated from core Scala and moved to Akka
  • 79. PARALLELCOLLECTIONS Most of the sequential Scala collections can be turned into a parallel counterpart with the par function. Some points about parallel collections: The main use case for parallel collections is when you need to apply a side-effect free computation to each element of the collection and the order does not matter. The computation should be non-trivial to see performance gains. Parallel collections are implemented on top of the Java fork-join framework.
  • 80. PARALLELCOLLECTIONS EXAMPLE Following example calculates factorials for each element in the collection. The numbers are quite big to make the computation more costly.
  • 81. def factorial(n: BigInt) = { @tailrec def calc(n: BigInt, acc: BigInt): BigInt = if (n == 0) acc else calc(n - 1, acc * n) calc(n, 1) } val numbers = BigInt(100000) to BigInt(100012) def measure(work: => Unit) { val start = System.currentTimeMillis work val end = System.currentTimeMillis println(end - start) } // my machine 4 cores // 12 computations // 12 / 4 => should get roughly 3x increase in performance // sequential measure(numbers.map(factorial)) // ~3 minutes // parallel measure(numbers.par.map(factorial)) // ~1 minute
  • 82. ACTORS The actor model represents a share-nothing message- passing programming model that is easier to understand for developers than shared mutable data with locks. Actor is an object that has an inbox to receive messages. Actor can process only one message at a time. Actors communicate with each other by sending immutable message objects using the ! method.
  • 83. ACTOR BENEFITS No shared data No locks & synchronization Asynchronous message passing Actors can share a thread pool Combine actors with java.util.concurrent classes. For example, multiple actors can share a ConcurrentHashMap Akka offers many other benefits such as support for distributed actors and fault tolerance, but that is another subject
  • 84. ACTOR USECASES Simulating workflows Distributed computing (with scatter-gather actor design pattern) Systems that need event driven architecture
  • 87.
  • 89. MESSAGES Let's define the messages as case classes so they can be pattern matched by actors. case class StartSprint() case class Develop(story: String) case class FixBug(story: String) case class DevelopmentDone(story: String) case class Test(story: String) case class TestingDone(story: String, bug: Boolean) case class Release(story: String) case class NewFeature(story: String)
  • 90. DEVELOPER ACTOR class Developer(val name: String) extends Actor { def receive = { case Develop(story) => develop(story) case FixBug(story) => fixBug(story) } def develop(story: String) { println(name + " develops " + story) tracker ! DevelopmentDone(story) } def fixBug(story: String) { println(name + " fixes bug in " + story) tracker ! DevelopmentDone(story) } }
  • 91. TESTER ACTOR class Tester(val name: String) extends Actor { def receive = { case Test(story) => test(story) } def test(story: String) { val foundBug = Random.nextBoolean() val log = if (foundBug) name + " found a bug in " + story else name + " verified that " + story + " works" println(log) tracker ! TestingDone(story, foundBug) } }
  • 92. RELEASEMANAGER ACTOR class RM extends Actor { def receive = { case Release(story) => { println("RM deployed " + story + " to production") client ! NewFeature(story) } } }
  • 93. CLIENTACTOR class Client extends Actor { def receive = { case NewFeature(feature) => { println("Client tries out " + feature + " and is satisfied with it") } } }
  • 94. TRACKER ACTOR As seen from the diagrams the Tracker actor coordinates the work between developers, testers and the release manager. class Tracker(stories: Seq[String]) extends Actor { /** * Map of Story -> (Dev, Tester) * Each story gets assigned a developer and a tester. */ val sprintPlan = { val numberOfStories = stories.size def repeat[T](resources: Seq[T]) = Stream.continually(resources).flatten.take(numberOfStories) val assignments = (stories, repeat(developers), repeat(testers)).zipped.toList assignments.map { case (story, dev, tester) => (story, (dev, tester)) }.toMap }
  • 95. APPCONTEXT Container that creates the actor system. object AppContext { println("Setting up AppContext...") val actorContext = ActorSystem("SprintAppActors") val tracker = { val stories = for (i <- 1 to 10) yield "Feature-" + i toActor(new Tracker(stories), "tracker") } val developers = toActors(List("Rasmeet", "Viral", "Dhruv"), (name: String) => new Developer(name), "developers") val testers = toActors(List("Dilip", "Shaishav"), (name: String) => new Tester(name), "testers") val val releaseManager = toActor(new RM, "RM") val client = toActor(new Client, "Client") def toActors[T](xs: Seq[T], fn: T => Actor, groupName: String) = xs.zipWithIndex.map { case (x, i) => toActor(fn(x), groupName + "-" + i)
  • 96. LAUNCHTHEAPP import AppContext._ object Simulation { def main(args: Array[String]) { tracker ! StartSprint } }
  • 97. SAMPLEOUTPUT Setting up AppContext... Starting sprint Rasmeet develops Feature-10 Viral develops Feature-5 Dhruv develops Feature-6 Dhruv develops Feature-9 Dhruv develops Feature-3 Rasmeet develops Feature-1 Viral develops Feature-2 Rasmeet develops Feature-7 Viral develops Feature-8 Rasmeet develops Feature-4 Shaishav found a bug in Feature-5 Dilip verified that Feature-6 works Shaishav verified that Feature-2 works Shaishav verified that Feature-8 works Dilip found a bug in Feature-10 Dilip verified that Feature-9 works Dilip found a bug in Feature-3 Dilip found a bug in Feature-1 Dilip verified that Feature-7 works Dilip found a bug in Feature-4 Viral fixes bug in Feature-5 RM deployed Feature-6 to production Rasmeet fixes bug in Feature-10 Rasmeet fixes bug in Feature-1
  • 99. OBSERVATIONS IDE. Intellij is currently hands down the best IDE for Scala. Eclipse Scala plugin is coming along but still has too many bugs and quirks to make it worthwile. Also, Eclipse in general has been getting slower with each successive release.
  • 100. OBSERVATIONS Code is really concise. Passing functions to other functions is awesome. I really do feel encouraged to write immutable classes and avoid changing state as Scala makes it easy to write without ceremony. The downside is that developers can write too concise code that becomes hard to read. Best advice is to try to keep the code simple even if it means writing a bit more code.
  • 101. OBSERVATIONS It's easy to interop with existing Java code. However, it's not so easy to call some of the Scala code from Java.
  • 102. OBSERVATIONS Scala method definitions can be hard to understand. // Wut me supposed to do wit it??? scan[B >: A, That](z: B)(op: (B, B) ? B)(implicit cbf: CanBuildFrom[List[A], // Huh? :+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Repr, B, That]): That
  • 103. OBSERVATIONS When the team uses Scala code reviews become very important. People with different programming backgrounds will use Scala differently. Haskell guys will write it as if it were Haskell. Java guys will write it as if it were Java. In general it's better to lean towards FP principles as it tends to produce code that is more reusable and is easier to understand in isolation.
  • 104. OBSERVATIONS Scala really shines when it comes to mixing OOP with FP, but it's not a good language to learn FP. You will benefit a lot if you get your hands dirty with Haskell or Clojure and then come back to Scala with a new perspective.
  • 105. SCALAADOPTION STRATEGY Decide as a team whether you want to use Scala. This is key. Start by writing test cases in Scala. You will be only using basic vanilla Scala, but at least it will give you confidence that you can effectively use Scala together with the existing code base. If you're introducing a new backend component or breaking up an existing monolithic component give Scala a chance.
  • 106. LEARNINGMATERIALS Free online Scala course on Coursera Programming In Scala 2nd ed Scala in Depth Functional Programming in Scala Twitter's Scala School Official documentation Akka documentation Scala Days 2013 videos InfoQ Scala presentations 99 Scala problems