SlideShare a Scribd company logo
An Introduction to Scala 
Andreas Neumann, 
Senior Software Engineer! 
a.neumann@clueda.com
Overview 
⬤A very short history of Scala! 
⬤Using Scala - Basics: Compile and run! 
⬤Introduction to the core concepts : vals, classes, objects, traits, control 
structures and functions! 
⬤Some intermediate concepts in Scala: Pattern Matching, Option, XML, Futures! 
⬤Patterns in Scala! 
⬤Functional Style 
Clueda AG 
2
About Scala 
⬤A JVM Languge! 
⬤multiparadigmatic! 
⬤functional object orientated 
Clueda AG 
3
The father of Scala - Martin Odersky 
⬤Professor EPFL! 
⬤Java-Compiler! 
⬤Java 1.4 Generics! 
⬤PIZZA! 
⬤Scala! 
⬤Co-Founder Typesafe 
Clueda AG 
4
The company behind Scala - 
⬤Training! 
⬤Consulting! 
⬤Scala! 
⬤Actor! 
⬤Play 
Clueda AG 
5
Who is using Scala 
⬤Xerox! 
⬤Twitter! 
⬤Foursquare! 
⬤Sony! 
⬤Siemens! 
⬤clueda! 
⬤… 
Clueda AG 
6
Nice features 
⬤Can be integrated in any Java based architecture! 
⬤support concurrent and asynchronous operations out of the box in many 
flavors (Futures,Parallel Collections, Akka)! 
⬤great for embedded DSLs 
Clueda AG 
7
Introduction 
⬤Run code / compile Code! 
⬤Syntax (some tips)! 
⬤declare variables! 
⬤functions! 
⬤clases, traits and objects 
Clueda AG 
8
Run code, compile sources 
⬤Scala can be used in many different environments:! 
⬤compile and run on a JVM! 
⬤run as a script! 
⬤in an interactive console, called REPL 
Clueda AG 
9
Scala - compiler / scalac 
⬤the compiler is called scalac! 
⬤The sources are compiled to 
Java byte code! 
⬤*.class! 
⬤run class with scala <name> 
Clueda AG 
10
Scripting with Scala - Unix 
⬤Scala can be used as scripting language! 
⬤change mode to executeable or run by bash 
Clueda AG 
11 
#!/bin/sh 
exec scala "$0" "$@" 
!# 
! 
object HelloWorld { 
def main(args: Array[String]) { 
println("Hello, world! " + 
args.toList) 
} 
} 
HelloWorld.main(args)
Scripting with Scala - Windows 
⬤Resembles UNIX use a batch script instead! 
⬤*.bat! 
⬤run 
Clueda AG 
12 
::#!! 
@echo off! 
call scala %0 %*! 
goto :eof! 
::!#! ! 
object HelloWorld {! 
def main(args: Array[String]) {! 
println("Hello, world! " +! 
args.toList)! 
}! 
}! 
! 
HelloWorld.main(args)
Scala - Interpreter / REPL 
⬤part of the scala installation! 
⬤Start by typing scala the shell! 
⬤:q or CTRL + d to quit 
Clueda AG 
13 
neumann@mac ~> scala! 
!! 
Welcome to Scala version 2.11.1 (Java HotSpot(TM) ! 
64-Bit Server VM, Java 1.7.0_55).! 
Type in expressions to have them evaluated.! 
Type :help for more information.! 
! 
scala> println("Hello World")! 
Hello World! 
! 
scala> :q! 
!! 
neumann@mac ~>
Online REPL 
⬤https://codebrew.io/ 
Clueda AG 
14
Syntax 
⬤No need for „;“ , one expression per line ! 
⬤Still possible to add ; if for example you want several expression within one line! 
⬤The dot on method invocations can be dropped. It is best practice to do so with 
infix invocation but not with postfix operations. 
Clueda AG 
15 
"Hallo Welt !".split(" ")! 
//res0: Array[String] = Array(Hallo, Welt, !)! ! 
scala> "Hallo Welt !" split " " ! 
//res2: Array[String] = Array(Hallo, Welt, !) 
scala> List(1,2.3).map(_ * 3).head! 
//res3: Double = 3.0! ! 
scala> ( List(1,2.3) map (_ * 3) ).head! 
//res4: Double = 3.0
val, vars 
⬤val creates a Value which is not changeable ( like final modifier in Java)! 
⬤var creates a Variable , which can be reassigned different values 
Clueda AG 
16
Example: val and var 
Clueda AG 
17 
val x = 42! 
//x: Int = 42! 
! 
var y = 99! 
//y: Int = 99! 
! 
y = 1! 
y: Int = 1! 
! 
x = 1! 
error: reassignment to val! 
x = 1! 
^
Types and type inferrence 
⬤Types are introduced after : which is written behind the var/val! 
! 
⬤Giving the type explicitly is optional as the type inference can infer the type. It’s 
considered good style to add the type information nonetheless. 
Clueda AG 
18 
s : String = "ein String" 
val a = "Hallo"! 
//a: java.lang.String = Hallo! 
! 
val b = 1! 
//b: Int = 1! 
! 
val c = 3.5! 
//c: Double = 3.5! 
! 
val d = List(1,2.0)! 
//d: List[Double] = List(1.0, 2.0)
define methods 
⬤methods are introduced with def! 
⬤optionally there can be a list of 
parameters enclosed by parentheses! 
⬤then the body of the function! 
⬤methods returning a value put a 
between name arguments and the 
body! 
⬤the result of the last expression 
evaluated within the body is the 
return value 
Clueda AG 
19 
def write(aString: String):Unit= 
{! 
println(aString) ! 
}! 
! 
write("Hallo ihr alle da 
draußen!")! 
//Hallo ihr alle da draußen! 
def add(x: Int, y:Int) : Int = { ! 
x + y! 
}! 
! 
add(40,2)! 
//res0: Int = 42
Collections 
⬤Scala has a big Collections library! 
⬤Collections provide similar interfaces as far as possible! 
⬤Most collections come in up to four flavors:! 
⬤basic (mostly = immutable)! 
⬤immutable! 
⬤mutable! 
⬤parallel 
Clueda AG 
20
Scala basic collection tree 
Clueda AG 
21
Scala collections - immutable 
Clueda AG 
22
Scala collections - mutable 
Clueda AG 
23
Scala Collections Example : List (1 / 2) 
Clueda AG 
24 
val a = List("a","b","c")! 
// a: List[java.lang.String] = List(a, b, c)! 
val b = List(1,2,3)! 
//b: List[Int] = List(1, 2, 3)! 
! 
a.head! 
// java.lang.String = a! 
a.tail! 
// List[java.lang.String] = List(b, c)! 
! 
0 :: b! 
// List[Int] = List(0, 1, 2, 3)! 
a ++ b! 
// List[Any] = List(a, b, c, 1, 2, 3)! 
a zip b! 
// List[(java.lang.String, Int)] = List((a,1), (b,2), (c,3))! 
a.sliding(2).toList! 
// List[List[String]] = List(List(a, b), List(b, c))!
Scala Collections : Map 
Clueda AG 
25 
val counting = Map(1 -> "eins", 2 -> "zwei", 3 -> "drei")! 
// counting: scala.collection.immutable.Map[Int,java.lang.String] =! 
// Map((1,eins), (2,zwei), (3,drei))! 
! 
counting(2)! 
//java.lang.String = zwei! 
! 
counting.get(2)! 
//Option[java.lang.String] = Some(zwei)! 
! 
counting get 99! 
// Option[java.lang.String] = None!
Classes 
⬤Classes are introduced by the keyword class ! 
⬤Optionally each class has constructor elements in parentheses! 
⬤optionally there is a class body! 
⬤Things to look out for! 
⬤Constructor elements prepended with the keyword val automatically get a 
getter method with the same name as the val (uniform access principle)! 
⬤Constructor elements prepended with the keyword var get a getter method 
and a setter method with the same name as the var (uniform access 
principle)! 
⬤Every expression within the body gets evaluated and called on object 
creation time 
Clueda AG 
26
Example: A scala class 
⬤Instances are created with new <ClassName> 
Clueda AG 
27 
class Document(val title: String, val author: String, yearInt: Int) {! 
! 
val year = yearInt.toString! 
! 
def shortCitation: String = author + " : " + title + ". " + year! 
}! 
! 
val scalaBook = ! 
! new Document("Programming In Scala","Martin Odersky",2011)! 
! 
println(scalaBook.title)! 
println(scalaBook.year)!
Scala Objects 
⬤Objects are created using the keyword object! 
⬤They have NO constructor! 
⬤Works roughly like a java class with static methods! 
⬤Calling members ObjectName.member or ObjectName.method! 
⬤Singleton-Object 
Clueda AG 
28
Scala Object - Example 
Clueda AG 
29 
object DeepThought {! 
! 
! val theMeaningOfLife =! 
"The meaning of life: 42"! 
! 
! def speak {! 
println(theMeaningOfLife)! 
}! 
! 
}! 
! 
DeepThought.speak! 
//The meaning of life: 42
Companion Object 
⬤Widely used pattern in Scala! 
⬤A object with the same name as a class! 
⬤Native Constructor Pattern 
Clueda AG 
30
Case Class 
⬤Introduce using the keywords case class! 
⬤Like a „normal class“! 
⬤Defines a companion object automatically with apply, unapply and some other 
methods! 
⬤All constructor elements have getter methods as if prepended by val! 
⬤Adds hashCode and equals based on the constructor Elements! 
⬤Other classes must not inherit from case classes 
Clueda AG 
31
Case Class - Example 
Clueda AG 
32 
case class Book(title: String, pages :Int)! 
//defined class Book! 
! 
val book = Book("Necronomicon",1000)! 
//book: Book = Book(Necronomicon,1000)! 
! 
println( book.title )! 
//Necronomicon! 
! 
book == Book("Necronomicon",1000)! 
//Boolean = true! 
! 
scala> book.hashCode! 
//-364191203! 
! 
scala> Book("Necronomicon",1000).hashCode! 
//-364191203
Trait 
⬤introduced with keyword trait! 
⬤roughly comparable to a java interface! 
⬤allows an effect resembling multiple inheritance without the dangers (i.e. 
diamond of death)! 
⬤small building blocks! 
⬤like ruby mixins 
Clueda AG 
33
Trait - Example 
⬤Two „traits“ are defined as 
Traits: Edible and ExoticTaste! 
⬤Two classes are defined: 
Cake, which implements 
edible and ChiliChoc 
implements Edible and 
ExoticTaste 
Clueda AG 
34 
!! 
trait Edible {! 
! def taste: String! 
! def eat = println(taste)! 
}! 
! trait ExoticTaste {! 
! def eat: Unit! def describeTaste = {! 
! ! eat! 
! ! println("It tastes exotic")! 
! }! 
}! !! 
case class Cake() extends Edible {! 
! def taste = "sweet"! 
}! ! 
case class ChilliChoc(taste: String) ! 
! ! ! ! ! ! extends Edible with 
ExoticTaste
Trait - Example : Usage 
Clueda AG 
35 
val cake = new Cake()! 
cake.eat! ! 
val chilliChoc = ChilliChoc("sweet and hot")! ! 
chilliChoc.eat! 
chilliChoc.describeTaste 
scala> val cake = new Cake()! 
cake: Cake = Cake()! ! 
scala> cake.eat! 
sweet! !! 
scala> val chilliChoc = ChilliChoc("sweet and hot")! 
chilliChoc: ChilliChoc = ChilliChoc(sweet and hot)! ! 
scala> chilliChoc.eat! 
sweet and hot! ! 
scala> chilliChoc.describeTaste! 
sweet and hot! 
It tastes exotic
control structures 
⬤if, else! 
⬤while! 
⬤foreach, map! 
⬤for-comprehensions 
Clueda AG 
36
Control structures 
⬤Control structures like while, if and else work as in Java or C! 
⬤In contrast to Java, control structures are functions, i.e. they return a value! 
⬤while always returns returns Unit 
Clueda AG 
37 
val x = if ( 1 < 2 ) true! 
//x: AnyVal = true
functional control structures 
⬤some Examples! 
⬤map : Apply function to each given element , keep result (like looping and 
collecting the results)! 
! 
! 
⬤foreach: Apply function to each given element , drop result 
Clueda AG 
38 
List(1,2,3,4) map (x => x + 1)! 
//res1: List[Int] = List(2, 3, 4, 5) 
List(1,2,3) foreach ( x => println(s"And a $x") )! 
! 
//And a 1! 
//And a 2! 
//And a 3
matching 
⬤Pattern matching! 
⬤keyword match! 
⬤A group of cases introduced with the keyword case ! 
⬤Switch on Steroids! 
⬤Pattern Guards allow better control flow! 
⬤Case Classes and Extractor Patterns for easy deconstruction and 
extraction of input 
Clueda AG 
39
Matching Example 
Clueda AG 
40 
books: List[Any] = ! 
List(Book(Programming Scala,883,2012), 
Book(Programming Pearl,1104,2000), Book(Necronomicon, 
666,666), Ein String, 5, 42)! !b 
ookComments: List[String] = ! 
List(New Scala Book by Martin Odersky from 2012, 
Programming Pearl 1104 2000, Necronomicon 666 666, 
Something else, Something else, an integer bigger than 10)! 
case class Book( title: String, pages: Int, year: 
Int)! ! 
val books = List( ! 
! Book("Programming Scala", 883, 2012),! 
! Book("Programming Pearl", 1104, 2000),! 
! Book("Necronomicon",666,666),! 
! "Ein String“, 5, 42! 
)! ! 
val bookComments = books map {! 
! case Book("Programming Scala", pages, year) 
=> ! 
! ! s"New Scala Book by Martin Odersky 
from $year"! 
! case Book(title, pages,year) => ! 
! ! s"$title $pages $year"! 
! case x: Int if x > 10 => ! 
! ! "an integer bigger than 10"! 
! case _ => ! 
! ! "Something else"! 
}
For-Comprehensions 
⬤program with a DSL that looks a lot like pseudocode! 
⬤will be translated to map, filter, flatMap and reduce operations by the compiler 
Clueda AG 
41 
def isEven(x: Int) = x % 2 == 0! 
val integers = for {! 
x <- 1 to 99! 
if isEven(x)! 
if x % 5 == 0! 
} yield x! 
//integers: scala.collection.immutable.IndexedSeq[Int] = ! 
Vector(10, 20, 30, 40, 50, 60, 70, 80, 90) 
~ Translated ~! 
(1 to 99) filter isEven filter ( _ % 5 == 0)
Some language features 
⬤Strings: Interpolation and MultilineStrings! 
⬤Option[Type]! 
⬤Future[X]! 
⬤XML erzeugen und bearbeiten! 
⬤Reguläre Ausdrücke! 
⬤Parallele Collections! 
⬤Implicits 
Clueda AG 
42
String Interpolation 
⬤String concatenation works with „+“! 
! 
! 
⬤String interpolation: prepending String with „s“ marking Variable with $! 
! 
! 
⬤Complex Expressions are enclosed within ${ } 
Clueda AG 
43 
"hello" + " " + "world"! 
//res2: String = hello world 
val w = "world"! 
s"hello $w"! 
//res3: String = hello world 
val w = "world"! 
s"$w has length:${w.length}"! 
//res4: String = world has length:5!
String Concatenation/Interpolation - Example 
Clueda AG 
44 
val names = List("Roger","Felix", "Bene")! 
! 
for (name <- names) println("Hello" + name)! 
! 
//HelloRoger! 
//HelloFelix! 
//HelloBene 
val names = List("Roger","Felix", "Bene")! 
! 
for (name <- names) println(s"Hello $name")! 
! 
//Hello Roger! 
//Hello Felix! 
//Hello Bene
Multiline String 
⬤Multiline String is created by using """ """ instead of " " ! 
! 
! 
! 
! 
! 
! 
⬤allows embedding " in Strings and gets rid of double Escapes 
Clueda AG 
"""This! 
| is a! 
| multiline String! 
| """! 
! 
res6: String =! 
"This! 
is a! 
multiline String! 
" 
45 
"""Hello "World"! """! 
//res12: String = "Hello "World"! "
Combined example Strings 
Clueda AG 
46 
val names = List("Roger","Felix", "Bene")! 
! 
for (name <- names) println(! 
s"""Hello $name your name! 
has length:${ name.size }! 
and reads backwards as:"${ name.reverse}"! 
"""! 
) 
Hello Roger your name! 
has length:5! 
and reads backwards as:"regoR"! ! 
Hello Felix your name! 
has length:5! 
and reads backwards as:"xileF"! ! 
Hello Bene your name! 
has length:4! 
and reads backwards as:"eneB"
String format - The f interpolator 
⬤prepend String with f ““! 
⬤Syntax like C printf 
Clueda AG 
47 
def euroToDollar(euro: Double): Double = ! 
! ! euro * 1.352065! 
! 
val euro = List(1,2.5,5.12)! 
! 
euro map euroToDollar foreach { d =>! 
println(f"Got $d%2.2f ($d)")! 
} 
Got 1,35 (1.352065)! 
Got 3,38 (3.3801625)! 
Got 6,92 (6.9225728)
The Option-Type 
⬤Marks functions that may return a result but also may not return a result! 
⬤Comes in two flavors: Some and None! 
! 
! 
! 
! 
⬤like maybe in Haskell! 
⬤A way to get around checking for null all the time 
Clueda AG 
48 
val x : Option[_] = None! 
//x: Option[_] = None! 
! 
val x : Option[_] = Some("Hello World!")! 
//x: Option[_] = Some(Hello World!)
Option / List Comparison 
⬤Option behaves like a list with one element! 
! 
! 
⬤An empty Option is called None. None behaves like an empty list. 
Clueda AG 
49 
List( 1 ) map (i => i + 0.5 ) ! 
//List[Double] = List(1.5) 
Some( 1 ) map (i => i + 0.5 )! 
//Option[Double] = Some(1.5) 
val y : List[Int] = List()! 
//y: List[Int] = List()! 
! 
y map (i => i+ 0.5)! 
//List[Double] = List() 
// Like an empty List! 
val x : Option[Int] = None ! 
//x: Option[Int] = None! 
x map (i => i+ 0.5)! 
// Option[Double] = None
Option-Type Beispiel: Option vs. null 
Clueda AG 
50 
val bigBangPHD = Map(! 
"Leonard" -> "Ph.D.",! 
"Sheldon" -> "Ph.D.,Sc.D",! 
"Rajesh" -> "Ph.D"! 
)! 
! 
val friends = List("Leonard","Sheldon","Rajesh","Howard") 
bigBangPHD("Leonard")! 
//res0: java.lang.String = Ph.D.! 
! 
bigBangPHD("Howard")! 
java.util.NoSuchElementException: key not 
found: Howard! 
! at scala.collection.MapLike 
$class.default(MapLike.scala:223)! 
! at scala.collection.immutable.Map 
$Map3.default(Map.scala:132) 
bigBangPHD get "Leonard"! 
//res1: Option[java.lang.String] ! 
= Some(Ph.D.)! 
! 
bigBangPHD.get("Sheldon")! 
//res2: Option[java.lang.String] ! 
= Some(Ph.D., Sc.D)! 
! 
bigBangPHD.get("Howard")! 
//res3: Option[java.lang.String] ! 
= None
Option -Type :Examples 1 
⬤Used widely throughout Scala! 
⬤many builtin methods to handle Option 
Clueda AG 
51 
// Liste mit Options erzeugen ! 
friends map (bigBangPHD.get(_))! 
friends map bigBangPHD.get! 
//List[Option[java.lang.String]] = ! 
//List(Some(Ph.D.), Some(Ph.D.,Sc.D), Some(Ph.D), None)! !! 
// flatten entfernt None und „entpackt“ Some(thing)! 
friends map bigBangPHD.get flatten! 
friends flatMap (f => bigBangPHD.get(f))! 
/!/res5: List[java.lang.String] = List(Ph.D., Ph.D.,Sc.D, Ph.D)! 
// for comprehensions wenden Operationen nur auf Some() an und verwerfen None! 
for {! 
! person <- friends! 
! phd <- bigBangPHD get person! 
} yield s"$person has a $phd"! 
//List[java.lang.String] = ! 
//List(Leonard has a Ph.D., Sheldon has a Ph.D.,Sc.D, Rajesh has a Ph.D)
Option -Type : Examples 2‚ 
⬤Option ist tief in Scala integriert! 
⬤Es existieren viele Methoden die mit Option umgehen können 
// getOrElse erlaubt es einen Standardrückgabewert für None anzugeben, ansonsten wird Some(thing) „ausgepackt“! 
friends! 
! .map( n =>(n,bigBangPHD.get(n)) ) // creates Tuple! 
! .map{ case (n,d) => ! 
! ! ! ! n + " " + d.getOrElse("Sheldon tells me you only have a master's degree.") ! 
! }! //res7: List[java.lang.String] = ! 
//List(Leonard Ph.D.,! 
//Sheldon Ph.D.,Sc.D,! 
//Rajesh Ph.D,! 
//Howard Sheldon tells me you only have a master's degree.)! ! 
// Option Types besitzen Extraktoren für Pattern Matching! 
friends map bigBangPHD.get zip friends map {! 
Clueda AG 
52 
case (Some(phd), name ) => name + " : " + phd! 
case (None, name) => name + " is just an engineer"! 
}! ! 
//res10: List[java.lang.String] = List(Leonard : Ph.D.,! 
//Sheldon : Ph.D.,Sc.D,! 
//Rajesh : Ph.D,! 
//Howard is just an engineer)
Futures 
⬤Are a way to abstract over asynchronous computation! 
⬤non blocking! 
⬤can be used much like Option! 
⬤used in many popular Scala libraries 
Clueda AG 
53
Futures - Plumbing 
⬤Import com.scala.concurrent._ for future helpers! 
⬤Every future needs an ExcecutionContext 
Clueda AG 
54 
import scala.concurrent._! 
import ExecutionContext.Implicits.global
Using Futures - Example 
val urls = ! 
List("http://www.clueda.de","http://www.neumann.biz","http://www.an-it.com")! 
! 
def takeTime = { code to measure time }! 
def extractURLs(data: String) : Iterator[String] = …! 
def printURLs(data: String) : Unit = extractURLs(data) foreach println! 
def printLinks = urls map ( url => printURLs( getData(url) ) )! 
! 
takeTime( printLinks )! 
takeTime( future { printLinks } )! 
Clueda AG 
55 
scala> takeTime( printLinks )! 
Url -> /favicon.gif! 
Url -> /stylesheets/refinery/style.css! 
Url -> /stylesheets/style.css?1380179036! 
…! 
res9: (String, List[Unit]) = ! 
! (! 
! ! took 2.109 s,! 
! ! List((), (), ())! 
! ) 
takeTime( future { printLinks } )! 
res10: (String, scala.concurrent.Future[List[Unit]]) = ! 
! (! 
! ! took 0.0 s,! 
! ! 
scala.concurrent.impl.Promise$DefaultPromise@..! 
! 
)! scala> Url -> /favicon.gif! 
Url -> /stylesheets/refinery/style.css! 
Url -> /stylesheets/style.css?1380179036! 
Url -> /stylesheets/flexslider.css?1349423712! 
…
Futures - Getting the result 
⬤To get the result of a Future you have to block and wait! 
! 
! 
⬤This is usually bad! 
⬤Awaiting the result should happen as late as possible as it negates the benefits 
one gets using futures 
Clueda AG 
56 
import scala.concurrent.duration._! ! 
takeTime( Await.result( Future(printLinks), 10 seconds )) 
scala> takeTime( Await.result( Future(printLinks), 10 seconds )) 
warning: there were 1 feature warning(s); re-run with -feature for details 
Url -> /favicon.gif 
Url -> /stylesheets/refinery/style.css 
Url -> /stylesheets/style.css?1380179036 
Url -> /stylesheets/flexslider.css?1349423712 
… 
res30: (String, List[Unit]) = (took 1.976 s,List((), (), ()))
Futures - Composing 
⬤As futures are Monads ( said it, done! ) they can be composed! 
⬤The futures run asynchronously and will not wait for each other but await will 
wait till the last of the futures has completed or the timeout is reached. 
Clueda AG 
57 
def composedFutures: Future[(Unit,Unit,Unit)] = {! 
! val f1 = Future( getAndPrintLinks("http://www.an-it.com") )! 
! val f2 = Future( getAndPrintLinks("http://www.neumann.biz") )! 
! val f3 = Future( getAndPrintLinks("http://www.clueda.com") )! 
! 
! for ( d1 <- f1 ; d2 <- f2 ; d3 <- f3) yield (d1,d2,d3)! 
} 
takeTime { Await.result(composedFutures,10 seconds) } 
warning: there were 1 feature warning(s); re-run with -feature for details 
Url -> /stylesheets/an-it.css?1339665275 
Url -> mobile_stylesheets/mobile.css 
Url -> / 
Url -> ethnologie-studium 
res21: (String, (Unit, Unit, Unit)) = (took 0.834 s,((),(),()))
XML in Scala 
⬤XML is a first class language citizen as string is in Java or Ruby! 
⬤It’s possible to embed XML in Scala source code and get syntax highlighting 
Clueda AG 
58
Scala - XML 
⬤Xml can be written within scala sources! 
⬤IDE s provide syntax-highlighting (Eclipse, Netbeans, IntelliJ)! 
⬤Code can be embedded using { } within XML literals 
Clueda AG 
59
Emit XML - Example 
Clueda AG 
60 
case class Book( title: String, pages: Int, year: Int) {! 
! 
def toXML = ! 
<book>! 
<title>{title}</title>! 
<pages>{pages toString}</pages>! 
<year>{year toString}</year>! 
</book>! 
! 
}! 
! 
val books = List( ! 
Book("Programming Scala", 883, 2012),! 
Book("Programming Perl", 1104, 2000),! 
Book("Necronomicon",666,666) ! 
)! 
! 
for ( book <- books) {! 
println(book.toXML)! 
}
Emitted XML 
Clueda AG 
61 
<book>! 
<title>Programming Scala</title>! 
<pages>883</pages>! 
<year>2012</year>! 
</book>! 
<book>! 
<title>Programming Perl</title>! 
<pages>1104</pages>! 
<year>2000</year>! 
</book>! 
<book>! 
<title>Necronomicon</title>! 
<pages>666</pages>! 
<year>666</year>! 
</book>!
Processing XML 
⬤Scala provides an internal DSL influence providing a XPath like syntax ( 
instead of // and  instead of / )! 
⬤<xml></xml>  "tag" : Shallow -Match! 
⬤<xml></xml>  "tag" : Deep -Match! 
⬤<xml attribute=„wert“></xml>  "@attribut" : Deep -Match on a XML attribute! 
⬤(<xml></xml>  "tag").text : Extracts the text value of an xml node 
Clueda AG 
62
processing XML - Example 
Clueda AG 
63 
case class Book( title: String, pages: Int, year: Int) {! 
def toXML = ! 
<book>! 
<title>{title}</title>! 
<pages>{pages}</pages>! 
<year>{year}</year>! 
</book>! 
! 
implicit def intToString(in : Int) : String = in.toString! 
}! 
! 
object Book {! 
def fromXML(bookXML: scala.xml.NodeSeq) : Book= {! 
val title = (bookXML  "title").text! 
val pages = (bookXML  "pages").text.toInt! 
val year = (bookXML  "year").text.toInt! 
new Book(title, pages, year)! 
}! 
}
processing XML - Result 
Clueda AG 
64 
val books = ! 
<books>! 
<book>! 
<title>Programming Scala</title>! 
<pages>883</pages>! 
<year>2012</year>! 
</book>! 
<book>! 
<title>Programming Perl</title>! 
<pages>1104</pages>! 
<year>2000</year>! 
</book>! 
<book>! 
<title>Necronomicon</title>! 
<pages>666</pages>! 
<year>666</year>! 
</book>! 
</books>! ! 
val booksInstances = (books  „book") map Book.fromXML! 
val booksPages = (books  "pages").map(_.text.toInt)! 
booksInstances: scala.collection.immutable.Seq[Book] = ! 
List(Book(Programming Scala,883,2012), Book(Programming Perl,1104,2000), Book(Necronomicon,666,666))! 
booksPages: scala.collection.immutable.Seq[Int] = List(883, 1104, 666)
Regular Expressions 
⬤Creating a regular Expression:.r aus einem String erzeugen: ! 
! 
! 
! 
! 
! 
⬤Uses Java-Regex-Engine to create a NFA! 
⬤Regex-Object also implement extractors for pattern matching 
Clueda AG 
65 
// Using the Constructor! 
new scala.util.matching.Regex("hrefs?=s?"([^"]+)"")! 
//Changing a string to a regex with the .r method! 
"hrefs?=s?"([^"]+)"".r! 
// Using """ , no need to escape " and double escaping of ! 
"""hrefs?=s?"([^"]+)"""".r !
Regex - Usage 
Clueda AG 
66 
import scala.io.Source! 
! 
val html = (Source fromURL "http://www.clueda.com").getLines mkString ""! 
! 
val urlExtractor = """hrefs?=s?"([^"]+)"""".r! 
! 
for ( urlExtractor(url) <- urlExtractor findAllIn html ) { ! 
! println(s"Url -> $url")! 
}
first-order-functions / anonymous functions 
⬤functions have a type like Integer or String! 
⬤They can be arguments to function and passed around as values 
Clueda AG 
67 
val y = (x: Int) => x * x! 
//y: (Int) => Int = ! 
! 
y apply 5! 
// Int = 25! 
! 
y(5)! 
// Int = 25! 
! 
val add = (x: Int, y: Int) => x + y! 
// add: (Int, Int) => Int = ! 
! 
add(1,2)! 
// Int = 3
Implicits 
⬤are introduced using the keyword implicit! 
⬤trigger an automatic transformation! 
⬤not stackable! 
⬤shorter, more readable! 
⬤may introduce „magic“! 
⬤Pimp my library Pattern: Locally scopefied monkey patching 
Clueda AG 
68
Implicits: Example 
⬤no more need to manually transform year to string when using xml! 
⬤will also work for all other integers in scope of Book 
Clueda AG 
69 
case class Book( title: String, pages: Int, year: Int) {! 
def toXML = ! 
<book>! 
<title>{title}</title>! 
<pages>{pages}</pages>! 
<year>{year}</year>! 
</book>! 
! 
implicit def intToString(in : Int) : String = in.toString! 
}
Parallel Collections 
⬤Asynchronous, parallel processing to take advantage of multicore processors! 
⬤.par transforms a Collection to it’s parallel counterpart! 
⬤.seq transforms a parallel Collection to a sequential one! 
⬤Parallel is implemented as a trait => can be used to create own par collections! 
⬤Also works for Map 
Clueda AG 
70
Parallel Collections - Example 
// Sequential! 
(1 to 10) foreach println 
Clueda AG 
71 
// Parallel! 
(1 to 10).par foreach println
Parallele Collections - Examples II 
Clueda AG 
72 
scala> tenTimes foreach println! 
10! 
80! 
90! 
60! 
30! 
70! 
100! 
20! 
40! 
50 
scala> tenTimes.seq foreach println! 
10! 
20! 
30! 
40! 
50! 
60! 
70! 
80! 
90! 
100 
// Unordered! 
val tenTimes = (1 to 10).par map (_ * 10) ! 
tenTimes foreach println 
// Unordered! 
val tenTimes = (1 to 10).par map (_ * 10) ! 
tenTimes foreach println! ! 
//Ordered! 
//.seq transforms a parallel collection to a sequential one! 
tenTimes.seq foreach println
Build your own control structures 
⬤Curried functions can be used to build control structures 
Clueda AG 
73 
object ControlStructures {! 
def unless( test: => Boolean)(action: => Any) = ! 
if (! test) action! ! 
def times( n: Int )(action: => Unit) {! 
(1 to n) foreach { _ => action}! 
}! 
} 
scala> import ControlStructures._! 
/!/import ControlStructures._! 
scala> times(2) { println("Hoorray :)")}! 
Hoorray :)! 
H!oorray :)! 
scala> unless (5 < 10) { println("Math stopped working.") }! 
/!/ Any = ()! 
scala> val ifNot = unless (2 + 2 != 4) { "Math still works." }! 
// Any = Math still works.!
Scala - Patterns 
⬤Structural Typing! 
⬤Pimp-My-Library-Pattern 
Clueda AG 
74
Structural Typing 
⬤Classed are described by methods and return types they provide! 
⬤Works like duck typing but the checking happens in compile time, not run time 
Clueda AG 
75 
class Cowboy { def shout = "Yehaaw !" }! 
class Pirate { def shout = "Arrrgh !" }! 
! 
def sayHelloTo( person : { def shout: String} ) = ! 
! s"Me : Hello!n $person shouts ${person.shout}" 
val johnWayne = new Cowboy! ! 
sayHelloTo(johnWayne)! 
scala> sayHelloTo(johnWayne)! 
res4: String =! 
Me : Hello!! 
Cowboy@185f8f75 shouts 
Yehaaw ! 
val guybrush = new Pirate! ! 
sayHelloTo(guybrush)! 
scala> sayHelloTo(guybrush)! 
res5: String =! 
Me : Hello!! 
Pirate@29c356d3 shouts Arrrgh !
Pimp-My-Library-Pattern 
⬤Add new functions to existing libraries without changing the code! 
⬤Like monkey patching! 
⬤type safe! 
⬤scoped 
Clueda AG 
76
Pimp-My-Library-Pattern : Example Source 
Clueda AG 
77 
object PimpString {! 
! 
class WeatherString(s: String) {! 
def ☀ = { println(s"$s sunny!") }! 
def ☁ = "Dont't forget your ☂!“! 
}! 
! 
implicit class ♔(name : String) {! 
def hail = s"Hail to king $name"! 
}! 
! 
implicit def pimpString(in: String) : WeatherString = ! 
!new WeatherString(in)! 
}!
Pimp-My-Library-Pattern : Example Usage 
Clueda AG 
⬤Use with caution ! 
scala> import PimpString._! 
import PimpString._! ! 
scala> "Monday is" ☀! 
Monday is sunny!! ! 
scala> "???".☁! 
res8: String = Dont't forget your ☂ 
scala> val anotherKing = ♔("Louis")! 
anotherKing: PimpString.♔ = PimpString$$u2654@12359094! ! 
scala> val aKing = implicitly[♔]("George")! 
aKing: PimpString.♔ = PimpString$$u2654@5081371! ! 
scala> aKing.hail! 
res10: String = Hail to king George 
78 
scala> val guys = List("James", "Louis", "Franz-Ferdinand")! 
guys: List[String] = List(James, Louis, Franz-Ferdinand)! ! 
scala> guys map (_.hail)! 
res13: List[String] = List(Hail to king James, Hail to king Louis, Hail to king Franz- 
Ferdinand)
Scala - imperative, object oriented, functional 
Clueda AG 
79
Scala -imperative, object oriented, functional - Rules of the thumb 
⬤functional if possible! 
⬤Sometimes imperative is better and faster ! 
⬤start out with val and immutable collections,switch to var or mutable collections 
if needed! 
⬤Use object orientation to encapsulate side effects and imperative code 
Clueda AG 
80
Advantage of the functional approach 
⬤short! 
⬤no side effects -> easier to reason about! 
⬤composeable 
Clueda AG 
81
Advantage of the imperative approach 
⬤familiar! 
⬤Eventually everything will be iterative after being translated to machine code 
Clueda AG 
82
Imperative vs. functional, Examples 
var i = 0! 
while (i < args.length) {! 
if ( i != 0 )! 
print(" ")! 
print( args(i) )! 
i += 1! 
}! 
println() 
Clueda AG 
83 
Imperative Functional 
var x = 1! 
var sum = 0! 
while (x <= 9999) {! 
sum += x! 
x += 1! 
}! 
(1 to 9999) foldLeft(0)(_ + _) 
(1 to 9999) sum 
println( args mkString " " ) 
println( ! 
args reduceOption ( (acc,arg ) => ! 
acc + " " + arg! 
)! 
)
Imperative vs. functional, Examples 2 
Clueda AG 
84 
Imperative Functional 
var i = null! 
var data = gettingData()! ! 
if (data != null && data.size > 0) ! 
! i = data(0)! 
else ! 
! i = 42! 
val i = ! 
! if (data != null && data.size > 0)! 
! ! data(0)! 
! else! 
! ! 42 
val i = ! 
! gettingData().headOption getOrElse 42
Literatur: 
⬤Wampler, D., & Payne, A. (2009). Programming Scala. Sebastopol, CA: 
O'Reilly.! 
⬤Odersky, M., Spoon, L., & Venners, B. (2008). Programming in Scala. 
Mountain View, Calif: Artima.! 
⬤Malayeri, M. “Pimp My Library” Is An Affront To Pimpers Of The World, 
Everywhere! 
⬤http://www.scala-lang.org! 
⬤http://www.an-it.com 
Clueda AG 
85
Thanks for participating :) 
Clueda AG 
86

More Related Content

What's hot

CoffeeScript
CoffeeScriptCoffeeScript
CoffeeScript
None
 
Ruby on Rails 中級者を目指して - 大場寧子
Ruby on Rails 中級者を目指して - 大場寧子Ruby on Rails 中級者を目指して - 大場寧子
Ruby on Rails 中級者を目指して - 大場寧子
Yasuko Ohba
 
Don't panic in Fortaleza - ScalaFX
Don't panic in Fortaleza - ScalaFXDon't panic in Fortaleza - ScalaFX
Don't panic in Fortaleza - ScalaFX
Alain Béarez
 
Live coding scala 'the java of the future'
Live coding scala 'the java of the future'Live coding scala 'the java of the future'
Live coding scala 'the java of the future'
Xebia Nederland BV
 
Code for Startup MVP (Ruby on Rails) Session 2
Code for Startup MVP (Ruby on Rails) Session 2Code for Startup MVP (Ruby on Rails) Session 2
Code for Startup MVP (Ruby on Rails) Session 2
Henry S
 
Coffee Script
Coffee ScriptCoffee Script
Coffee Script
Michal Taberski
 
TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012
TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012
TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012
Amazon Web Services
 
Deep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line InterfaceDeep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line Interface
Amazon Web Services
 
Gatling - Paris Perf User Group
Gatling - Paris Perf User GroupGatling - Paris Perf User Group
Gatling - Paris Perf User Group
slandelle
 
Introduction to Swift 2
Introduction to Swift 2Introduction to Swift 2
Introduction to Swift 2
Joris Timmerman
 
Moose
MooseMoose
Advanced fun with Objective-C runtime.
Advanced fun with Objective-C runtime.Advanced fun with Objective-C runtime.
Advanced fun with Objective-C runtime.
Sash Zats
 
AddressBook.swift
AddressBook.swiftAddressBook.swift
AddressBook.swift
Alexsander Akers
 
"Javascript" por Tiago Rodrigues
"Javascript" por Tiago Rodrigues"Javascript" por Tiago Rodrigues
Working with Cocoa and Objective-C
Working with Cocoa and Objective-CWorking with Cocoa and Objective-C
Working with Cocoa and Objective-C
Kazunobu Tasaka
 
Defensive Coding Crash Course Tutorial
Defensive Coding Crash Course TutorialDefensive Coding Crash Course Tutorial
Defensive Coding Crash Course Tutorial
Mark Niebergall
 
مقایسه و بررسی چهارچوب ریلز
مقایسه و بررسی چهارچوب ریلزمقایسه و بررسی چهارچوب ریلز
مقایسه و بررسی چهارچوب ریلز
railsbootcamp
 
Alfresco the clojure way
Alfresco the clojure wayAlfresco the clojure way
Alfresco the clojure way
Carlo Sciolla
 
Oral presentation v2
Oral presentation v2Oral presentation v2
Oral presentation v2
Yeqi He
 
What's New in ES6 for Web Devs
What's New in ES6 for Web DevsWhat's New in ES6 for Web Devs
What's New in ES6 for Web Devs
Rami Sayar
 

What's hot (20)

CoffeeScript
CoffeeScriptCoffeeScript
CoffeeScript
 
Ruby on Rails 中級者を目指して - 大場寧子
Ruby on Rails 中級者を目指して - 大場寧子Ruby on Rails 中級者を目指して - 大場寧子
Ruby on Rails 中級者を目指して - 大場寧子
 
Don't panic in Fortaleza - ScalaFX
Don't panic in Fortaleza - ScalaFXDon't panic in Fortaleza - ScalaFX
Don't panic in Fortaleza - ScalaFX
 
Live coding scala 'the java of the future'
Live coding scala 'the java of the future'Live coding scala 'the java of the future'
Live coding scala 'the java of the future'
 
Code for Startup MVP (Ruby on Rails) Session 2
Code for Startup MVP (Ruby on Rails) Session 2Code for Startup MVP (Ruby on Rails) Session 2
Code for Startup MVP (Ruby on Rails) Session 2
 
Coffee Script
Coffee ScriptCoffee Script
Coffee Script
 
TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012
TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012
TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012
 
Deep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line InterfaceDeep Dive: AWS Command Line Interface
Deep Dive: AWS Command Line Interface
 
Gatling - Paris Perf User Group
Gatling - Paris Perf User GroupGatling - Paris Perf User Group
Gatling - Paris Perf User Group
 
Introduction to Swift 2
Introduction to Swift 2Introduction to Swift 2
Introduction to Swift 2
 
Moose
MooseMoose
Moose
 
Advanced fun with Objective-C runtime.
Advanced fun with Objective-C runtime.Advanced fun with Objective-C runtime.
Advanced fun with Objective-C runtime.
 
AddressBook.swift
AddressBook.swiftAddressBook.swift
AddressBook.swift
 
"Javascript" por Tiago Rodrigues
"Javascript" por Tiago Rodrigues"Javascript" por Tiago Rodrigues
"Javascript" por Tiago Rodrigues
 
Working with Cocoa and Objective-C
Working with Cocoa and Objective-CWorking with Cocoa and Objective-C
Working with Cocoa and Objective-C
 
Defensive Coding Crash Course Tutorial
Defensive Coding Crash Course TutorialDefensive Coding Crash Course Tutorial
Defensive Coding Crash Course Tutorial
 
مقایسه و بررسی چهارچوب ریلز
مقایسه و بررسی چهارچوب ریلزمقایسه و بررسی چهارچوب ریلز
مقایسه و بررسی چهارچوب ریلز
 
Alfresco the clojure way
Alfresco the clojure wayAlfresco the clojure way
Alfresco the clojure way
 
Oral presentation v2
Oral presentation v2Oral presentation v2
Oral presentation v2
 
What's New in ES6 for Web Devs
What's New in ES6 for Web DevsWhat's New in ES6 for Web Devs
What's New in ES6 for Web Devs
 

Viewers also liked

Functional Scala I
Functional Scala IFunctional Scala I
Functional Scala I
Mario Gleichmann
 
Functional Scala II (in practice)
Functional Scala II (in practice)Functional Scala II (in practice)
Functional Scala II (in practice)
Mario Gleichmann
 
Scala 2.10.0 (english version)
Scala 2.10.0 (english version)Scala 2.10.0 (english version)
Scala 2.10.0 (english version)
Daniel Sobral
 
Scala for Java Developers (Silicon Valley Code Camp 13)
Scala for Java Developers (Silicon Valley Code Camp 13)Scala for Java Developers (Silicon Valley Code Camp 13)
Scala for Java Developers (Silicon Valley Code Camp 13)
Ramnivas Laddad
 
Scala For Java Programmers
Scala For Java ProgrammersScala For Java Programmers
Scala For Java Programmers
Enno Runne
 
Erkenntnisse aus Social Data gewinnen
Erkenntnisse aus Social Data gewinnenErkenntnisse aus Social Data gewinnen
Erkenntnisse aus Social Data gewinnen
Clueda AG
 
BITKOM 2015 Clueda Almax Vortrag
BITKOM 2015 Clueda Almax VortragBITKOM 2015 Clueda Almax Vortrag
BITKOM 2015 Clueda Almax Vortrag
Clueda AG
 
Big Data - Gold panning in the information age
Big Data - Gold panning in the information ageBig Data - Gold panning in the information age
Big Data - Gold panning in the information age
Clueda AG
 
Social Data: technische Herausforderungen, rechtliche Hürden und wirtschaftli...
Social Data: technische Herausforderungen, rechtliche Hürden und wirtschaftli...Social Data: technische Herausforderungen, rechtliche Hürden und wirtschaftli...
Social Data: technische Herausforderungen, rechtliche Hürden und wirtschaftli...
Clueda AG
 
Clueda
CluedaClueda
Clueda - Baader Investment Conference 2014
Clueda - Baader Investment Conference 2014Clueda - Baader Investment Conference 2014
Clueda - Baader Investment Conference 2014
Clueda AG
 
Real-Time Text Analytics at Predictive Analytics World berlin 2014
Real-Time Text Analytics at Predictive Analytics World berlin 2014Real-Time Text Analytics at Predictive Analytics World berlin 2014
Real-Time Text Analytics at Predictive Analytics World berlin 2014Clueda AG
 

Viewers also liked (12)

Functional Scala I
Functional Scala IFunctional Scala I
Functional Scala I
 
Functional Scala II (in practice)
Functional Scala II (in practice)Functional Scala II (in practice)
Functional Scala II (in practice)
 
Scala 2.10.0 (english version)
Scala 2.10.0 (english version)Scala 2.10.0 (english version)
Scala 2.10.0 (english version)
 
Scala for Java Developers (Silicon Valley Code Camp 13)
Scala for Java Developers (Silicon Valley Code Camp 13)Scala for Java Developers (Silicon Valley Code Camp 13)
Scala for Java Developers (Silicon Valley Code Camp 13)
 
Scala For Java Programmers
Scala For Java ProgrammersScala For Java Programmers
Scala For Java Programmers
 
Erkenntnisse aus Social Data gewinnen
Erkenntnisse aus Social Data gewinnenErkenntnisse aus Social Data gewinnen
Erkenntnisse aus Social Data gewinnen
 
BITKOM 2015 Clueda Almax Vortrag
BITKOM 2015 Clueda Almax VortragBITKOM 2015 Clueda Almax Vortrag
BITKOM 2015 Clueda Almax Vortrag
 
Big Data - Gold panning in the information age
Big Data - Gold panning in the information ageBig Data - Gold panning in the information age
Big Data - Gold panning in the information age
 
Social Data: technische Herausforderungen, rechtliche Hürden und wirtschaftli...
Social Data: technische Herausforderungen, rechtliche Hürden und wirtschaftli...Social Data: technische Herausforderungen, rechtliche Hürden und wirtschaftli...
Social Data: technische Herausforderungen, rechtliche Hürden und wirtschaftli...
 
Clueda
CluedaClueda
Clueda
 
Clueda - Baader Investment Conference 2014
Clueda - Baader Investment Conference 2014Clueda - Baader Investment Conference 2014
Clueda - Baader Investment Conference 2014
 
Real-Time Text Analytics at Predictive Analytics World berlin 2014
Real-Time Text Analytics at Predictive Analytics World berlin 2014Real-Time Text Analytics at Predictive Analytics World berlin 2014
Real-Time Text Analytics at Predictive Analytics World berlin 2014
 

Similar to Scala Workshop

Introduction to Scala : Clueda
Introduction to Scala : CluedaIntroduction to Scala : Clueda
Introduction to Scala : Clueda
Andreas Neumann
 
Introduction to Scala | Big Data Hadoop Spark Tutorial | CloudxLab
Introduction to Scala | Big Data Hadoop Spark Tutorial | CloudxLabIntroduction to Scala | Big Data Hadoop Spark Tutorial | CloudxLab
Introduction to Scala | Big Data Hadoop Spark Tutorial | CloudxLab
CloudxLab
 
Scala final ppt vinay
Scala final ppt vinayScala final ppt vinay
Scala final ppt vinay
Viplav Jain
 
TypeScript: coding JavaScript without the pain
TypeScript: coding JavaScript without the painTypeScript: coding JavaScript without the pain
TypeScript: coding JavaScript without the pain
Sander Mak (@Sander_Mak)
 
Scala presentationjune112011
Scala presentationjune112011Scala presentationjune112011
Scala presentationjune112011
PrasannaKumar Sathyanarayanan
 
楽々Scalaプログラミング
楽々Scalaプログラミング楽々Scalaプログラミング
楽々Scalaプログラミング
Tomoharu ASAMI
 
Introduction to Scala language
Introduction to Scala languageIntroduction to Scala language
Introduction to Scala language
Aaqib Pervaiz
 
Scalding - the not-so-basics @ ScalaDays 2014
Scalding - the not-so-basics @ ScalaDays 2014Scalding - the not-so-basics @ ScalaDays 2014
Scalding - the not-so-basics @ ScalaDays 2014
Konrad Malawski
 
Effective Scala (JavaDay Riga 2013)
Effective Scala (JavaDay Riga 2013)Effective Scala (JavaDay Riga 2013)
Effective Scala (JavaDay Riga 2013)
mircodotta
 
Qcon2011 functions rockpresentation_scala
Qcon2011 functions rockpresentation_scalaQcon2011 functions rockpresentation_scala
Qcon2011 functions rockpresentation_scala
Michael Stal
 
Solid and Sustainable Development in Scala
Solid and Sustainable Development in ScalaSolid and Sustainable Development in Scala
Solid and Sustainable Development in Scala
scalaconfjp
 
Solid And Sustainable Development in Scala
Solid And Sustainable Development in ScalaSolid And Sustainable Development in Scala
Solid And Sustainable Development in Scala
Kazuhiro Sera
 
Scala in a nutshell by venkat
Scala in a nutshell by venkatScala in a nutshell by venkat
Scala in a nutshell by venkat
Venkateswaran Kandasamy
 
Quick introduction to scala
Quick introduction to scalaQuick introduction to scala
Quick introduction to scala
Mohammad Hossein Rimaz
 
Scala Days San Francisco
Scala Days San FranciscoScala Days San Francisco
Scala Days San Francisco
Martin Odersky
 
Getting Started With Scala
Getting Started With ScalaGetting Started With Scala
Getting Started With Scala
Meetu Maltiar
 
A Brief Intro to Scala
A Brief Intro to ScalaA Brief Intro to Scala
A Brief Intro to Scala
Tim Underwood
 
Scala active record
Scala active recordScala active record
Scala active record
鉄平 土佐
 
TDC 2012 - Patterns e Anti-Patterns em Ruby
TDC 2012 - Patterns e Anti-Patterns em RubyTDC 2012 - Patterns e Anti-Patterns em Ruby
TDC 2012 - Patterns e Anti-Patterns em Ruby
Fabio Akita
 
Scala elegant and exotic part 1
Scala  elegant and exotic part 1Scala  elegant and exotic part 1
Scala elegant and exotic part 1
VulcanMinds
 

Similar to Scala Workshop (20)

Introduction to Scala : Clueda
Introduction to Scala : CluedaIntroduction to Scala : Clueda
Introduction to Scala : Clueda
 
Introduction to Scala | Big Data Hadoop Spark Tutorial | CloudxLab
Introduction to Scala | Big Data Hadoop Spark Tutorial | CloudxLabIntroduction to Scala | Big Data Hadoop Spark Tutorial | CloudxLab
Introduction to Scala | Big Data Hadoop Spark Tutorial | CloudxLab
 
Scala final ppt vinay
Scala final ppt vinayScala final ppt vinay
Scala final ppt vinay
 
TypeScript: coding JavaScript without the pain
TypeScript: coding JavaScript without the painTypeScript: coding JavaScript without the pain
TypeScript: coding JavaScript without the pain
 
Scala presentationjune112011
Scala presentationjune112011Scala presentationjune112011
Scala presentationjune112011
 
楽々Scalaプログラミング
楽々Scalaプログラミング楽々Scalaプログラミング
楽々Scalaプログラミング
 
Introduction to Scala language
Introduction to Scala languageIntroduction to Scala language
Introduction to Scala language
 
Scalding - the not-so-basics @ ScalaDays 2014
Scalding - the not-so-basics @ ScalaDays 2014Scalding - the not-so-basics @ ScalaDays 2014
Scalding - the not-so-basics @ ScalaDays 2014
 
Effective Scala (JavaDay Riga 2013)
Effective Scala (JavaDay Riga 2013)Effective Scala (JavaDay Riga 2013)
Effective Scala (JavaDay Riga 2013)
 
Qcon2011 functions rockpresentation_scala
Qcon2011 functions rockpresentation_scalaQcon2011 functions rockpresentation_scala
Qcon2011 functions rockpresentation_scala
 
Solid and Sustainable Development in Scala
Solid and Sustainable Development in ScalaSolid and Sustainable Development in Scala
Solid and Sustainable Development in Scala
 
Solid And Sustainable Development in Scala
Solid And Sustainable Development in ScalaSolid And Sustainable Development in Scala
Solid And Sustainable Development in Scala
 
Scala in a nutshell by venkat
Scala in a nutshell by venkatScala in a nutshell by venkat
Scala in a nutshell by venkat
 
Quick introduction to scala
Quick introduction to scalaQuick introduction to scala
Quick introduction to scala
 
Scala Days San Francisco
Scala Days San FranciscoScala Days San Francisco
Scala Days San Francisco
 
Getting Started With Scala
Getting Started With ScalaGetting Started With Scala
Getting Started With Scala
 
A Brief Intro to Scala
A Brief Intro to ScalaA Brief Intro to Scala
A Brief Intro to Scala
 
Scala active record
Scala active recordScala active record
Scala active record
 
TDC 2012 - Patterns e Anti-Patterns em Ruby
TDC 2012 - Patterns e Anti-Patterns em RubyTDC 2012 - Patterns e Anti-Patterns em Ruby
TDC 2012 - Patterns e Anti-Patterns em Ruby
 
Scala elegant and exotic part 1
Scala  elegant and exotic part 1Scala  elegant and exotic part 1
Scala elegant and exotic part 1
 

Recently uploaded

Analysis insight about a Flyball dog competition team's performance
Analysis insight about a Flyball dog competition team's performanceAnalysis insight about a Flyball dog competition team's performance
Analysis insight about a Flyball dog competition team's performance
roli9797
 
Global Situational Awareness of A.I. and where its headed
Global Situational Awareness of A.I. and where its headedGlobal Situational Awareness of A.I. and where its headed
Global Situational Awareness of A.I. and where its headed
vikram sood
 
在线办理(英国UCA毕业证书)创意艺术大学毕业证在读证明一模一样
在线办理(英国UCA毕业证书)创意艺术大学毕业证在读证明一模一样在线办理(英国UCA毕业证书)创意艺术大学毕业证在读证明一模一样
在线办理(英国UCA毕业证书)创意艺术大学毕业证在读证明一模一样
v7oacc3l
 
STATATHON: Unleashing the Power of Statistics in a 48-Hour Knowledge Extravag...
STATATHON: Unleashing the Power of Statistics in a 48-Hour Knowledge Extravag...STATATHON: Unleashing the Power of Statistics in a 48-Hour Knowledge Extravag...
STATATHON: Unleashing the Power of Statistics in a 48-Hour Knowledge Extravag...
sameer shah
 
The Ipsos - AI - Monitor 2024 Report.pdf
The  Ipsos - AI - Monitor 2024 Report.pdfThe  Ipsos - AI - Monitor 2024 Report.pdf
The Ipsos - AI - Monitor 2024 Report.pdf
Social Samosa
 
Experts live - Improving user adoption with AI
Experts live - Improving user adoption with AIExperts live - Improving user adoption with AI
Experts live - Improving user adoption with AI
jitskeb
 
Udemy_2024_Global_Learning_Skills_Trends_Report (1).pdf
Udemy_2024_Global_Learning_Skills_Trends_Report (1).pdfUdemy_2024_Global_Learning_Skills_Trends_Report (1).pdf
Udemy_2024_Global_Learning_Skills_Trends_Report (1).pdf
Fernanda Palhano
 
原版制作(unimelb毕业证书)墨尔本大学毕业证Offer一模一样
原版制作(unimelb毕业证书)墨尔本大学毕业证Offer一模一样原版制作(unimelb毕业证书)墨尔本大学毕业证Offer一模一样
原版制作(unimelb毕业证书)墨尔本大学毕业证Offer一模一样
ihavuls
 
原版一比一利兹贝克特大学毕业证(LeedsBeckett毕业证书)如何办理
原版一比一利兹贝克特大学毕业证(LeedsBeckett毕业证书)如何办理原版一比一利兹贝克特大学毕业证(LeedsBeckett毕业证书)如何办理
原版一比一利兹贝克特大学毕业证(LeedsBeckett毕业证书)如何办理
wyddcwye1
 
ViewShift: Hassle-free Dynamic Policy Enforcement for Every Data Lake
ViewShift: Hassle-free Dynamic Policy Enforcement for Every Data LakeViewShift: Hassle-free Dynamic Policy Enforcement for Every Data Lake
ViewShift: Hassle-free Dynamic Policy Enforcement for Every Data Lake
Walaa Eldin Moustafa
 
Learn SQL from basic queries to Advance queries
Learn SQL from basic queries to Advance queriesLearn SQL from basic queries to Advance queries
Learn SQL from basic queries to Advance queries
manishkhaire30
 
DSSML24_tspann_CodelessGenerativeAIPipelines
DSSML24_tspann_CodelessGenerativeAIPipelinesDSSML24_tspann_CodelessGenerativeAIPipelines
DSSML24_tspann_CodelessGenerativeAIPipelines
Timothy Spann
 
University of New South Wales degree offer diploma Transcript
University of New South Wales degree offer diploma TranscriptUniversity of New South Wales degree offer diploma Transcript
University of New South Wales degree offer diploma Transcript
soxrziqu
 
一比一原版(UCSF文凭证书)旧金山分校毕业证如何办理
一比一原版(UCSF文凭证书)旧金山分校毕业证如何办理一比一原版(UCSF文凭证书)旧金山分校毕业证如何办理
一比一原版(UCSF文凭证书)旧金山分校毕业证如何办理
nuttdpt
 
Everything you wanted to know about LIHTC
Everything you wanted to know about LIHTCEverything you wanted to know about LIHTC
Everything you wanted to know about LIHTC
Roger Valdez
 
一比一原版(GWU,GW文凭证书)乔治·华盛顿大学毕业证如何办理
一比一原版(GWU,GW文凭证书)乔治·华盛顿大学毕业证如何办理一比一原版(GWU,GW文凭证书)乔治·华盛顿大学毕业证如何办理
一比一原版(GWU,GW文凭证书)乔治·华盛顿大学毕业证如何办理
bopyb
 
Beyond the Basics of A/B Tests: Highly Innovative Experimentation Tactics You...
Beyond the Basics of A/B Tests: Highly Innovative Experimentation Tactics You...Beyond the Basics of A/B Tests: Highly Innovative Experimentation Tactics You...
Beyond the Basics of A/B Tests: Highly Innovative Experimentation Tactics You...
Aggregage
 
The Building Blocks of QuestDB, a Time Series Database
The Building Blocks of QuestDB, a Time Series DatabaseThe Building Blocks of QuestDB, a Time Series Database
The Building Blocks of QuestDB, a Time Series Database
javier ramirez
 
06-12-2024-BudapestDataForum-BuildingReal-timePipelineswithFLaNK AIM
06-12-2024-BudapestDataForum-BuildingReal-timePipelineswithFLaNK AIM06-12-2024-BudapestDataForum-BuildingReal-timePipelineswithFLaNK AIM
06-12-2024-BudapestDataForum-BuildingReal-timePipelineswithFLaNK AIM
Timothy Spann
 
一比一原版(UO毕业证)渥太华大学毕业证如何办理
一比一原版(UO毕业证)渥太华大学毕业证如何办理一比一原版(UO毕业证)渥太华大学毕业证如何办理
一比一原版(UO毕业证)渥太华大学毕业证如何办理
aqzctr7x
 

Recently uploaded (20)

Analysis insight about a Flyball dog competition team's performance
Analysis insight about a Flyball dog competition team's performanceAnalysis insight about a Flyball dog competition team's performance
Analysis insight about a Flyball dog competition team's performance
 
Global Situational Awareness of A.I. and where its headed
Global Situational Awareness of A.I. and where its headedGlobal Situational Awareness of A.I. and where its headed
Global Situational Awareness of A.I. and where its headed
 
在线办理(英国UCA毕业证书)创意艺术大学毕业证在读证明一模一样
在线办理(英国UCA毕业证书)创意艺术大学毕业证在读证明一模一样在线办理(英国UCA毕业证书)创意艺术大学毕业证在读证明一模一样
在线办理(英国UCA毕业证书)创意艺术大学毕业证在读证明一模一样
 
STATATHON: Unleashing the Power of Statistics in a 48-Hour Knowledge Extravag...
STATATHON: Unleashing the Power of Statistics in a 48-Hour Knowledge Extravag...STATATHON: Unleashing the Power of Statistics in a 48-Hour Knowledge Extravag...
STATATHON: Unleashing the Power of Statistics in a 48-Hour Knowledge Extravag...
 
The Ipsos - AI - Monitor 2024 Report.pdf
The  Ipsos - AI - Monitor 2024 Report.pdfThe  Ipsos - AI - Monitor 2024 Report.pdf
The Ipsos - AI - Monitor 2024 Report.pdf
 
Experts live - Improving user adoption with AI
Experts live - Improving user adoption with AIExperts live - Improving user adoption with AI
Experts live - Improving user adoption with AI
 
Udemy_2024_Global_Learning_Skills_Trends_Report (1).pdf
Udemy_2024_Global_Learning_Skills_Trends_Report (1).pdfUdemy_2024_Global_Learning_Skills_Trends_Report (1).pdf
Udemy_2024_Global_Learning_Skills_Trends_Report (1).pdf
 
原版制作(unimelb毕业证书)墨尔本大学毕业证Offer一模一样
原版制作(unimelb毕业证书)墨尔本大学毕业证Offer一模一样原版制作(unimelb毕业证书)墨尔本大学毕业证Offer一模一样
原版制作(unimelb毕业证书)墨尔本大学毕业证Offer一模一样
 
原版一比一利兹贝克特大学毕业证(LeedsBeckett毕业证书)如何办理
原版一比一利兹贝克特大学毕业证(LeedsBeckett毕业证书)如何办理原版一比一利兹贝克特大学毕业证(LeedsBeckett毕业证书)如何办理
原版一比一利兹贝克特大学毕业证(LeedsBeckett毕业证书)如何办理
 
ViewShift: Hassle-free Dynamic Policy Enforcement for Every Data Lake
ViewShift: Hassle-free Dynamic Policy Enforcement for Every Data LakeViewShift: Hassle-free Dynamic Policy Enforcement for Every Data Lake
ViewShift: Hassle-free Dynamic Policy Enforcement for Every Data Lake
 
Learn SQL from basic queries to Advance queries
Learn SQL from basic queries to Advance queriesLearn SQL from basic queries to Advance queries
Learn SQL from basic queries to Advance queries
 
DSSML24_tspann_CodelessGenerativeAIPipelines
DSSML24_tspann_CodelessGenerativeAIPipelinesDSSML24_tspann_CodelessGenerativeAIPipelines
DSSML24_tspann_CodelessGenerativeAIPipelines
 
University of New South Wales degree offer diploma Transcript
University of New South Wales degree offer diploma TranscriptUniversity of New South Wales degree offer diploma Transcript
University of New South Wales degree offer diploma Transcript
 
一比一原版(UCSF文凭证书)旧金山分校毕业证如何办理
一比一原版(UCSF文凭证书)旧金山分校毕业证如何办理一比一原版(UCSF文凭证书)旧金山分校毕业证如何办理
一比一原版(UCSF文凭证书)旧金山分校毕业证如何办理
 
Everything you wanted to know about LIHTC
Everything you wanted to know about LIHTCEverything you wanted to know about LIHTC
Everything you wanted to know about LIHTC
 
一比一原版(GWU,GW文凭证书)乔治·华盛顿大学毕业证如何办理
一比一原版(GWU,GW文凭证书)乔治·华盛顿大学毕业证如何办理一比一原版(GWU,GW文凭证书)乔治·华盛顿大学毕业证如何办理
一比一原版(GWU,GW文凭证书)乔治·华盛顿大学毕业证如何办理
 
Beyond the Basics of A/B Tests: Highly Innovative Experimentation Tactics You...
Beyond the Basics of A/B Tests: Highly Innovative Experimentation Tactics You...Beyond the Basics of A/B Tests: Highly Innovative Experimentation Tactics You...
Beyond the Basics of A/B Tests: Highly Innovative Experimentation Tactics You...
 
The Building Blocks of QuestDB, a Time Series Database
The Building Blocks of QuestDB, a Time Series DatabaseThe Building Blocks of QuestDB, a Time Series Database
The Building Blocks of QuestDB, a Time Series Database
 
06-12-2024-BudapestDataForum-BuildingReal-timePipelineswithFLaNK AIM
06-12-2024-BudapestDataForum-BuildingReal-timePipelineswithFLaNK AIM06-12-2024-BudapestDataForum-BuildingReal-timePipelineswithFLaNK AIM
06-12-2024-BudapestDataForum-BuildingReal-timePipelineswithFLaNK AIM
 
一比一原版(UO毕业证)渥太华大学毕业证如何办理
一比一原版(UO毕业证)渥太华大学毕业证如何办理一比一原版(UO毕业证)渥太华大学毕业证如何办理
一比一原版(UO毕业证)渥太华大学毕业证如何办理
 

Scala Workshop

  • 1. An Introduction to Scala Andreas Neumann, Senior Software Engineer! a.neumann@clueda.com
  • 2. Overview ⬤A very short history of Scala! ⬤Using Scala - Basics: Compile and run! ⬤Introduction to the core concepts : vals, classes, objects, traits, control structures and functions! ⬤Some intermediate concepts in Scala: Pattern Matching, Option, XML, Futures! ⬤Patterns in Scala! ⬤Functional Style Clueda AG 2
  • 3. About Scala ⬤A JVM Languge! ⬤multiparadigmatic! ⬤functional object orientated Clueda AG 3
  • 4. The father of Scala - Martin Odersky ⬤Professor EPFL! ⬤Java-Compiler! ⬤Java 1.4 Generics! ⬤PIZZA! ⬤Scala! ⬤Co-Founder Typesafe Clueda AG 4
  • 5. The company behind Scala - ⬤Training! ⬤Consulting! ⬤Scala! ⬤Actor! ⬤Play Clueda AG 5
  • 6. Who is using Scala ⬤Xerox! ⬤Twitter! ⬤Foursquare! ⬤Sony! ⬤Siemens! ⬤clueda! ⬤… Clueda AG 6
  • 7. Nice features ⬤Can be integrated in any Java based architecture! ⬤support concurrent and asynchronous operations out of the box in many flavors (Futures,Parallel Collections, Akka)! ⬤great for embedded DSLs Clueda AG 7
  • 8. Introduction ⬤Run code / compile Code! ⬤Syntax (some tips)! ⬤declare variables! ⬤functions! ⬤clases, traits and objects Clueda AG 8
  • 9. Run code, compile sources ⬤Scala can be used in many different environments:! ⬤compile and run on a JVM! ⬤run as a script! ⬤in an interactive console, called REPL Clueda AG 9
  • 10. Scala - compiler / scalac ⬤the compiler is called scalac! ⬤The sources are compiled to Java byte code! ⬤*.class! ⬤run class with scala <name> Clueda AG 10
  • 11. Scripting with Scala - Unix ⬤Scala can be used as scripting language! ⬤change mode to executeable or run by bash Clueda AG 11 #!/bin/sh exec scala "$0" "$@" !# ! object HelloWorld { def main(args: Array[String]) { println("Hello, world! " + args.toList) } } HelloWorld.main(args)
  • 12. Scripting with Scala - Windows ⬤Resembles UNIX use a batch script instead! ⬤*.bat! ⬤run Clueda AG 12 ::#!! @echo off! call scala %0 %*! goto :eof! ::!#! ! object HelloWorld {! def main(args: Array[String]) {! println("Hello, world! " +! args.toList)! }! }! ! HelloWorld.main(args)
  • 13. Scala - Interpreter / REPL ⬤part of the scala installation! ⬤Start by typing scala the shell! ⬤:q or CTRL + d to quit Clueda AG 13 neumann@mac ~> scala! !! Welcome to Scala version 2.11.1 (Java HotSpot(TM) ! 64-Bit Server VM, Java 1.7.0_55).! Type in expressions to have them evaluated.! Type :help for more information.! ! scala> println("Hello World")! Hello World! ! scala> :q! !! neumann@mac ~>
  • 15. Syntax ⬤No need for „;“ , one expression per line ! ⬤Still possible to add ; if for example you want several expression within one line! ⬤The dot on method invocations can be dropped. It is best practice to do so with infix invocation but not with postfix operations. Clueda AG 15 "Hallo Welt !".split(" ")! //res0: Array[String] = Array(Hallo, Welt, !)! ! scala> "Hallo Welt !" split " " ! //res2: Array[String] = Array(Hallo, Welt, !) scala> List(1,2.3).map(_ * 3).head! //res3: Double = 3.0! ! scala> ( List(1,2.3) map (_ * 3) ).head! //res4: Double = 3.0
  • 16. val, vars ⬤val creates a Value which is not changeable ( like final modifier in Java)! ⬤var creates a Variable , which can be reassigned different values Clueda AG 16
  • 17. Example: val and var Clueda AG 17 val x = 42! //x: Int = 42! ! var y = 99! //y: Int = 99! ! y = 1! y: Int = 1! ! x = 1! error: reassignment to val! x = 1! ^
  • 18. Types and type inferrence ⬤Types are introduced after : which is written behind the var/val! ! ⬤Giving the type explicitly is optional as the type inference can infer the type. It’s considered good style to add the type information nonetheless. Clueda AG 18 s : String = "ein String" val a = "Hallo"! //a: java.lang.String = Hallo! ! val b = 1! //b: Int = 1! ! val c = 3.5! //c: Double = 3.5! ! val d = List(1,2.0)! //d: List[Double] = List(1.0, 2.0)
  • 19. define methods ⬤methods are introduced with def! ⬤optionally there can be a list of parameters enclosed by parentheses! ⬤then the body of the function! ⬤methods returning a value put a between name arguments and the body! ⬤the result of the last expression evaluated within the body is the return value Clueda AG 19 def write(aString: String):Unit= {! println(aString) ! }! ! write("Hallo ihr alle da draußen!")! //Hallo ihr alle da draußen! def add(x: Int, y:Int) : Int = { ! x + y! }! ! add(40,2)! //res0: Int = 42
  • 20. Collections ⬤Scala has a big Collections library! ⬤Collections provide similar interfaces as far as possible! ⬤Most collections come in up to four flavors:! ⬤basic (mostly = immutable)! ⬤immutable! ⬤mutable! ⬤parallel Clueda AG 20
  • 21. Scala basic collection tree Clueda AG 21
  • 22. Scala collections - immutable Clueda AG 22
  • 23. Scala collections - mutable Clueda AG 23
  • 24. Scala Collections Example : List (1 / 2) Clueda AG 24 val a = List("a","b","c")! // a: List[java.lang.String] = List(a, b, c)! val b = List(1,2,3)! //b: List[Int] = List(1, 2, 3)! ! a.head! // java.lang.String = a! a.tail! // List[java.lang.String] = List(b, c)! ! 0 :: b! // List[Int] = List(0, 1, 2, 3)! a ++ b! // List[Any] = List(a, b, c, 1, 2, 3)! a zip b! // List[(java.lang.String, Int)] = List((a,1), (b,2), (c,3))! a.sliding(2).toList! // List[List[String]] = List(List(a, b), List(b, c))!
  • 25. Scala Collections : Map Clueda AG 25 val counting = Map(1 -> "eins", 2 -> "zwei", 3 -> "drei")! // counting: scala.collection.immutable.Map[Int,java.lang.String] =! // Map((1,eins), (2,zwei), (3,drei))! ! counting(2)! //java.lang.String = zwei! ! counting.get(2)! //Option[java.lang.String] = Some(zwei)! ! counting get 99! // Option[java.lang.String] = None!
  • 26. Classes ⬤Classes are introduced by the keyword class ! ⬤Optionally each class has constructor elements in parentheses! ⬤optionally there is a class body! ⬤Things to look out for! ⬤Constructor elements prepended with the keyword val automatically get a getter method with the same name as the val (uniform access principle)! ⬤Constructor elements prepended with the keyword var get a getter method and a setter method with the same name as the var (uniform access principle)! ⬤Every expression within the body gets evaluated and called on object creation time Clueda AG 26
  • 27. Example: A scala class ⬤Instances are created with new <ClassName> Clueda AG 27 class Document(val title: String, val author: String, yearInt: Int) {! ! val year = yearInt.toString! ! def shortCitation: String = author + " : " + title + ". " + year! }! ! val scalaBook = ! ! new Document("Programming In Scala","Martin Odersky",2011)! ! println(scalaBook.title)! println(scalaBook.year)!
  • 28. Scala Objects ⬤Objects are created using the keyword object! ⬤They have NO constructor! ⬤Works roughly like a java class with static methods! ⬤Calling members ObjectName.member or ObjectName.method! ⬤Singleton-Object Clueda AG 28
  • 29. Scala Object - Example Clueda AG 29 object DeepThought {! ! ! val theMeaningOfLife =! "The meaning of life: 42"! ! ! def speak {! println(theMeaningOfLife)! }! ! }! ! DeepThought.speak! //The meaning of life: 42
  • 30. Companion Object ⬤Widely used pattern in Scala! ⬤A object with the same name as a class! ⬤Native Constructor Pattern Clueda AG 30
  • 31. Case Class ⬤Introduce using the keywords case class! ⬤Like a „normal class“! ⬤Defines a companion object automatically with apply, unapply and some other methods! ⬤All constructor elements have getter methods as if prepended by val! ⬤Adds hashCode and equals based on the constructor Elements! ⬤Other classes must not inherit from case classes Clueda AG 31
  • 32. Case Class - Example Clueda AG 32 case class Book(title: String, pages :Int)! //defined class Book! ! val book = Book("Necronomicon",1000)! //book: Book = Book(Necronomicon,1000)! ! println( book.title )! //Necronomicon! ! book == Book("Necronomicon",1000)! //Boolean = true! ! scala> book.hashCode! //-364191203! ! scala> Book("Necronomicon",1000).hashCode! //-364191203
  • 33. Trait ⬤introduced with keyword trait! ⬤roughly comparable to a java interface! ⬤allows an effect resembling multiple inheritance without the dangers (i.e. diamond of death)! ⬤small building blocks! ⬤like ruby mixins Clueda AG 33
  • 34. Trait - Example ⬤Two „traits“ are defined as Traits: Edible and ExoticTaste! ⬤Two classes are defined: Cake, which implements edible and ChiliChoc implements Edible and ExoticTaste Clueda AG 34 !! trait Edible {! ! def taste: String! ! def eat = println(taste)! }! ! trait ExoticTaste {! ! def eat: Unit! def describeTaste = {! ! ! eat! ! ! println("It tastes exotic")! ! }! }! !! case class Cake() extends Edible {! ! def taste = "sweet"! }! ! case class ChilliChoc(taste: String) ! ! ! ! ! ! ! extends Edible with ExoticTaste
  • 35. Trait - Example : Usage Clueda AG 35 val cake = new Cake()! cake.eat! ! val chilliChoc = ChilliChoc("sweet and hot")! ! chilliChoc.eat! chilliChoc.describeTaste scala> val cake = new Cake()! cake: Cake = Cake()! ! scala> cake.eat! sweet! !! scala> val chilliChoc = ChilliChoc("sweet and hot")! chilliChoc: ChilliChoc = ChilliChoc(sweet and hot)! ! scala> chilliChoc.eat! sweet and hot! ! scala> chilliChoc.describeTaste! sweet and hot! It tastes exotic
  • 36. control structures ⬤if, else! ⬤while! ⬤foreach, map! ⬤for-comprehensions Clueda AG 36
  • 37. Control structures ⬤Control structures like while, if and else work as in Java or C! ⬤In contrast to Java, control structures are functions, i.e. they return a value! ⬤while always returns returns Unit Clueda AG 37 val x = if ( 1 < 2 ) true! //x: AnyVal = true
  • 38. functional control structures ⬤some Examples! ⬤map : Apply function to each given element , keep result (like looping and collecting the results)! ! ! ⬤foreach: Apply function to each given element , drop result Clueda AG 38 List(1,2,3,4) map (x => x + 1)! //res1: List[Int] = List(2, 3, 4, 5) List(1,2,3) foreach ( x => println(s"And a $x") )! ! //And a 1! //And a 2! //And a 3
  • 39. matching ⬤Pattern matching! ⬤keyword match! ⬤A group of cases introduced with the keyword case ! ⬤Switch on Steroids! ⬤Pattern Guards allow better control flow! ⬤Case Classes and Extractor Patterns for easy deconstruction and extraction of input Clueda AG 39
  • 40. Matching Example Clueda AG 40 books: List[Any] = ! List(Book(Programming Scala,883,2012), Book(Programming Pearl,1104,2000), Book(Necronomicon, 666,666), Ein String, 5, 42)! !b ookComments: List[String] = ! List(New Scala Book by Martin Odersky from 2012, Programming Pearl 1104 2000, Necronomicon 666 666, Something else, Something else, an integer bigger than 10)! case class Book( title: String, pages: Int, year: Int)! ! val books = List( ! ! Book("Programming Scala", 883, 2012),! ! Book("Programming Pearl", 1104, 2000),! ! Book("Necronomicon",666,666),! ! "Ein String“, 5, 42! )! ! val bookComments = books map {! ! case Book("Programming Scala", pages, year) => ! ! ! s"New Scala Book by Martin Odersky from $year"! ! case Book(title, pages,year) => ! ! ! s"$title $pages $year"! ! case x: Int if x > 10 => ! ! ! "an integer bigger than 10"! ! case _ => ! ! ! "Something else"! }
  • 41. For-Comprehensions ⬤program with a DSL that looks a lot like pseudocode! ⬤will be translated to map, filter, flatMap and reduce operations by the compiler Clueda AG 41 def isEven(x: Int) = x % 2 == 0! val integers = for {! x <- 1 to 99! if isEven(x)! if x % 5 == 0! } yield x! //integers: scala.collection.immutable.IndexedSeq[Int] = ! Vector(10, 20, 30, 40, 50, 60, 70, 80, 90) ~ Translated ~! (1 to 99) filter isEven filter ( _ % 5 == 0)
  • 42. Some language features ⬤Strings: Interpolation and MultilineStrings! ⬤Option[Type]! ⬤Future[X]! ⬤XML erzeugen und bearbeiten! ⬤Reguläre Ausdrücke! ⬤Parallele Collections! ⬤Implicits Clueda AG 42
  • 43. String Interpolation ⬤String concatenation works with „+“! ! ! ⬤String interpolation: prepending String with „s“ marking Variable with $! ! ! ⬤Complex Expressions are enclosed within ${ } Clueda AG 43 "hello" + " " + "world"! //res2: String = hello world val w = "world"! s"hello $w"! //res3: String = hello world val w = "world"! s"$w has length:${w.length}"! //res4: String = world has length:5!
  • 44. String Concatenation/Interpolation - Example Clueda AG 44 val names = List("Roger","Felix", "Bene")! ! for (name <- names) println("Hello" + name)! ! //HelloRoger! //HelloFelix! //HelloBene val names = List("Roger","Felix", "Bene")! ! for (name <- names) println(s"Hello $name")! ! //Hello Roger! //Hello Felix! //Hello Bene
  • 45. Multiline String ⬤Multiline String is created by using """ """ instead of " " ! ! ! ! ! ! ! ⬤allows embedding " in Strings and gets rid of double Escapes Clueda AG """This! | is a! | multiline String! | """! ! res6: String =! "This! is a! multiline String! " 45 """Hello "World"! """! //res12: String = "Hello "World"! "
  • 46. Combined example Strings Clueda AG 46 val names = List("Roger","Felix", "Bene")! ! for (name <- names) println(! s"""Hello $name your name! has length:${ name.size }! and reads backwards as:"${ name.reverse}"! """! ) Hello Roger your name! has length:5! and reads backwards as:"regoR"! ! Hello Felix your name! has length:5! and reads backwards as:"xileF"! ! Hello Bene your name! has length:4! and reads backwards as:"eneB"
  • 47. String format - The f interpolator ⬤prepend String with f ““! ⬤Syntax like C printf Clueda AG 47 def euroToDollar(euro: Double): Double = ! ! ! euro * 1.352065! ! val euro = List(1,2.5,5.12)! ! euro map euroToDollar foreach { d =>! println(f"Got $d%2.2f ($d)")! } Got 1,35 (1.352065)! Got 3,38 (3.3801625)! Got 6,92 (6.9225728)
  • 48. The Option-Type ⬤Marks functions that may return a result but also may not return a result! ⬤Comes in two flavors: Some and None! ! ! ! ! ⬤like maybe in Haskell! ⬤A way to get around checking for null all the time Clueda AG 48 val x : Option[_] = None! //x: Option[_] = None! ! val x : Option[_] = Some("Hello World!")! //x: Option[_] = Some(Hello World!)
  • 49. Option / List Comparison ⬤Option behaves like a list with one element! ! ! ⬤An empty Option is called None. None behaves like an empty list. Clueda AG 49 List( 1 ) map (i => i + 0.5 ) ! //List[Double] = List(1.5) Some( 1 ) map (i => i + 0.5 )! //Option[Double] = Some(1.5) val y : List[Int] = List()! //y: List[Int] = List()! ! y map (i => i+ 0.5)! //List[Double] = List() // Like an empty List! val x : Option[Int] = None ! //x: Option[Int] = None! x map (i => i+ 0.5)! // Option[Double] = None
  • 50. Option-Type Beispiel: Option vs. null Clueda AG 50 val bigBangPHD = Map(! "Leonard" -> "Ph.D.",! "Sheldon" -> "Ph.D.,Sc.D",! "Rajesh" -> "Ph.D"! )! ! val friends = List("Leonard","Sheldon","Rajesh","Howard") bigBangPHD("Leonard")! //res0: java.lang.String = Ph.D.! ! bigBangPHD("Howard")! java.util.NoSuchElementException: key not found: Howard! ! at scala.collection.MapLike $class.default(MapLike.scala:223)! ! at scala.collection.immutable.Map $Map3.default(Map.scala:132) bigBangPHD get "Leonard"! //res1: Option[java.lang.String] ! = Some(Ph.D.)! ! bigBangPHD.get("Sheldon")! //res2: Option[java.lang.String] ! = Some(Ph.D., Sc.D)! ! bigBangPHD.get("Howard")! //res3: Option[java.lang.String] ! = None
  • 51. Option -Type :Examples 1 ⬤Used widely throughout Scala! ⬤many builtin methods to handle Option Clueda AG 51 // Liste mit Options erzeugen ! friends map (bigBangPHD.get(_))! friends map bigBangPHD.get! //List[Option[java.lang.String]] = ! //List(Some(Ph.D.), Some(Ph.D.,Sc.D), Some(Ph.D), None)! !! // flatten entfernt None und „entpackt“ Some(thing)! friends map bigBangPHD.get flatten! friends flatMap (f => bigBangPHD.get(f))! /!/res5: List[java.lang.String] = List(Ph.D., Ph.D.,Sc.D, Ph.D)! // for comprehensions wenden Operationen nur auf Some() an und verwerfen None! for {! ! person <- friends! ! phd <- bigBangPHD get person! } yield s"$person has a $phd"! //List[java.lang.String] = ! //List(Leonard has a Ph.D., Sheldon has a Ph.D.,Sc.D, Rajesh has a Ph.D)
  • 52. Option -Type : Examples 2‚ ⬤Option ist tief in Scala integriert! ⬤Es existieren viele Methoden die mit Option umgehen können // getOrElse erlaubt es einen Standardrückgabewert für None anzugeben, ansonsten wird Some(thing) „ausgepackt“! friends! ! .map( n =>(n,bigBangPHD.get(n)) ) // creates Tuple! ! .map{ case (n,d) => ! ! ! ! ! n + " " + d.getOrElse("Sheldon tells me you only have a master's degree.") ! ! }! //res7: List[java.lang.String] = ! //List(Leonard Ph.D.,! //Sheldon Ph.D.,Sc.D,! //Rajesh Ph.D,! //Howard Sheldon tells me you only have a master's degree.)! ! // Option Types besitzen Extraktoren für Pattern Matching! friends map bigBangPHD.get zip friends map {! Clueda AG 52 case (Some(phd), name ) => name + " : " + phd! case (None, name) => name + " is just an engineer"! }! ! //res10: List[java.lang.String] = List(Leonard : Ph.D.,! //Sheldon : Ph.D.,Sc.D,! //Rajesh : Ph.D,! //Howard is just an engineer)
  • 53. Futures ⬤Are a way to abstract over asynchronous computation! ⬤non blocking! ⬤can be used much like Option! ⬤used in many popular Scala libraries Clueda AG 53
  • 54. Futures - Plumbing ⬤Import com.scala.concurrent._ for future helpers! ⬤Every future needs an ExcecutionContext Clueda AG 54 import scala.concurrent._! import ExecutionContext.Implicits.global
  • 55. Using Futures - Example val urls = ! List("http://www.clueda.de","http://www.neumann.biz","http://www.an-it.com")! ! def takeTime = { code to measure time }! def extractURLs(data: String) : Iterator[String] = …! def printURLs(data: String) : Unit = extractURLs(data) foreach println! def printLinks = urls map ( url => printURLs( getData(url) ) )! ! takeTime( printLinks )! takeTime( future { printLinks } )! Clueda AG 55 scala> takeTime( printLinks )! Url -> /favicon.gif! Url -> /stylesheets/refinery/style.css! Url -> /stylesheets/style.css?1380179036! …! res9: (String, List[Unit]) = ! ! (! ! ! took 2.109 s,! ! ! List((), (), ())! ! ) takeTime( future { printLinks } )! res10: (String, scala.concurrent.Future[List[Unit]]) = ! ! (! ! ! took 0.0 s,! ! ! scala.concurrent.impl.Promise$DefaultPromise@..! ! )! scala> Url -> /favicon.gif! Url -> /stylesheets/refinery/style.css! Url -> /stylesheets/style.css?1380179036! Url -> /stylesheets/flexslider.css?1349423712! …
  • 56. Futures - Getting the result ⬤To get the result of a Future you have to block and wait! ! ! ⬤This is usually bad! ⬤Awaiting the result should happen as late as possible as it negates the benefits one gets using futures Clueda AG 56 import scala.concurrent.duration._! ! takeTime( Await.result( Future(printLinks), 10 seconds )) scala> takeTime( Await.result( Future(printLinks), 10 seconds )) warning: there were 1 feature warning(s); re-run with -feature for details Url -> /favicon.gif Url -> /stylesheets/refinery/style.css Url -> /stylesheets/style.css?1380179036 Url -> /stylesheets/flexslider.css?1349423712 … res30: (String, List[Unit]) = (took 1.976 s,List((), (), ()))
  • 57. Futures - Composing ⬤As futures are Monads ( said it, done! ) they can be composed! ⬤The futures run asynchronously and will not wait for each other but await will wait till the last of the futures has completed or the timeout is reached. Clueda AG 57 def composedFutures: Future[(Unit,Unit,Unit)] = {! ! val f1 = Future( getAndPrintLinks("http://www.an-it.com") )! ! val f2 = Future( getAndPrintLinks("http://www.neumann.biz") )! ! val f3 = Future( getAndPrintLinks("http://www.clueda.com") )! ! ! for ( d1 <- f1 ; d2 <- f2 ; d3 <- f3) yield (d1,d2,d3)! } takeTime { Await.result(composedFutures,10 seconds) } warning: there were 1 feature warning(s); re-run with -feature for details Url -> /stylesheets/an-it.css?1339665275 Url -> mobile_stylesheets/mobile.css Url -> / Url -> ethnologie-studium res21: (String, (Unit, Unit, Unit)) = (took 0.834 s,((),(),()))
  • 58. XML in Scala ⬤XML is a first class language citizen as string is in Java or Ruby! ⬤It’s possible to embed XML in Scala source code and get syntax highlighting Clueda AG 58
  • 59. Scala - XML ⬤Xml can be written within scala sources! ⬤IDE s provide syntax-highlighting (Eclipse, Netbeans, IntelliJ)! ⬤Code can be embedded using { } within XML literals Clueda AG 59
  • 60. Emit XML - Example Clueda AG 60 case class Book( title: String, pages: Int, year: Int) {! ! def toXML = ! <book>! <title>{title}</title>! <pages>{pages toString}</pages>! <year>{year toString}</year>! </book>! ! }! ! val books = List( ! Book("Programming Scala", 883, 2012),! Book("Programming Perl", 1104, 2000),! Book("Necronomicon",666,666) ! )! ! for ( book <- books) {! println(book.toXML)! }
  • 61. Emitted XML Clueda AG 61 <book>! <title>Programming Scala</title>! <pages>883</pages>! <year>2012</year>! </book>! <book>! <title>Programming Perl</title>! <pages>1104</pages>! <year>2000</year>! </book>! <book>! <title>Necronomicon</title>! <pages>666</pages>! <year>666</year>! </book>!
  • 62. Processing XML ⬤Scala provides an internal DSL influence providing a XPath like syntax ( instead of // and instead of / )! ⬤<xml></xml> "tag" : Shallow -Match! ⬤<xml></xml> "tag" : Deep -Match! ⬤<xml attribute=„wert“></xml> "@attribut" : Deep -Match on a XML attribute! ⬤(<xml></xml> "tag").text : Extracts the text value of an xml node Clueda AG 62
  • 63. processing XML - Example Clueda AG 63 case class Book( title: String, pages: Int, year: Int) {! def toXML = ! <book>! <title>{title}</title>! <pages>{pages}</pages>! <year>{year}</year>! </book>! ! implicit def intToString(in : Int) : String = in.toString! }! ! object Book {! def fromXML(bookXML: scala.xml.NodeSeq) : Book= {! val title = (bookXML "title").text! val pages = (bookXML "pages").text.toInt! val year = (bookXML "year").text.toInt! new Book(title, pages, year)! }! }
  • 64. processing XML - Result Clueda AG 64 val books = ! <books>! <book>! <title>Programming Scala</title>! <pages>883</pages>! <year>2012</year>! </book>! <book>! <title>Programming Perl</title>! <pages>1104</pages>! <year>2000</year>! </book>! <book>! <title>Necronomicon</title>! <pages>666</pages>! <year>666</year>! </book>! </books>! ! val booksInstances = (books „book") map Book.fromXML! val booksPages = (books "pages").map(_.text.toInt)! booksInstances: scala.collection.immutable.Seq[Book] = ! List(Book(Programming Scala,883,2012), Book(Programming Perl,1104,2000), Book(Necronomicon,666,666))! booksPages: scala.collection.immutable.Seq[Int] = List(883, 1104, 666)
  • 65. Regular Expressions ⬤Creating a regular Expression:.r aus einem String erzeugen: ! ! ! ! ! ! ⬤Uses Java-Regex-Engine to create a NFA! ⬤Regex-Object also implement extractors for pattern matching Clueda AG 65 // Using the Constructor! new scala.util.matching.Regex("hrefs?=s?"([^"]+)"")! //Changing a string to a regex with the .r method! "hrefs?=s?"([^"]+)"".r! // Using """ , no need to escape " and double escaping of ! """hrefs?=s?"([^"]+)"""".r !
  • 66. Regex - Usage Clueda AG 66 import scala.io.Source! ! val html = (Source fromURL "http://www.clueda.com").getLines mkString ""! ! val urlExtractor = """hrefs?=s?"([^"]+)"""".r! ! for ( urlExtractor(url) <- urlExtractor findAllIn html ) { ! ! println(s"Url -> $url")! }
  • 67. first-order-functions / anonymous functions ⬤functions have a type like Integer or String! ⬤They can be arguments to function and passed around as values Clueda AG 67 val y = (x: Int) => x * x! //y: (Int) => Int = ! ! y apply 5! // Int = 25! ! y(5)! // Int = 25! ! val add = (x: Int, y: Int) => x + y! // add: (Int, Int) => Int = ! ! add(1,2)! // Int = 3
  • 68. Implicits ⬤are introduced using the keyword implicit! ⬤trigger an automatic transformation! ⬤not stackable! ⬤shorter, more readable! ⬤may introduce „magic“! ⬤Pimp my library Pattern: Locally scopefied monkey patching Clueda AG 68
  • 69. Implicits: Example ⬤no more need to manually transform year to string when using xml! ⬤will also work for all other integers in scope of Book Clueda AG 69 case class Book( title: String, pages: Int, year: Int) {! def toXML = ! <book>! <title>{title}</title>! <pages>{pages}</pages>! <year>{year}</year>! </book>! ! implicit def intToString(in : Int) : String = in.toString! }
  • 70. Parallel Collections ⬤Asynchronous, parallel processing to take advantage of multicore processors! ⬤.par transforms a Collection to it’s parallel counterpart! ⬤.seq transforms a parallel Collection to a sequential one! ⬤Parallel is implemented as a trait => can be used to create own par collections! ⬤Also works for Map Clueda AG 70
  • 71. Parallel Collections - Example // Sequential! (1 to 10) foreach println Clueda AG 71 // Parallel! (1 to 10).par foreach println
  • 72. Parallele Collections - Examples II Clueda AG 72 scala> tenTimes foreach println! 10! 80! 90! 60! 30! 70! 100! 20! 40! 50 scala> tenTimes.seq foreach println! 10! 20! 30! 40! 50! 60! 70! 80! 90! 100 // Unordered! val tenTimes = (1 to 10).par map (_ * 10) ! tenTimes foreach println // Unordered! val tenTimes = (1 to 10).par map (_ * 10) ! tenTimes foreach println! ! //Ordered! //.seq transforms a parallel collection to a sequential one! tenTimes.seq foreach println
  • 73. Build your own control structures ⬤Curried functions can be used to build control structures Clueda AG 73 object ControlStructures {! def unless( test: => Boolean)(action: => Any) = ! if (! test) action! ! def times( n: Int )(action: => Unit) {! (1 to n) foreach { _ => action}! }! } scala> import ControlStructures._! /!/import ControlStructures._! scala> times(2) { println("Hoorray :)")}! Hoorray :)! H!oorray :)! scala> unless (5 < 10) { println("Math stopped working.") }! /!/ Any = ()! scala> val ifNot = unless (2 + 2 != 4) { "Math still works." }! // Any = Math still works.!
  • 74. Scala - Patterns ⬤Structural Typing! ⬤Pimp-My-Library-Pattern Clueda AG 74
  • 75. Structural Typing ⬤Classed are described by methods and return types they provide! ⬤Works like duck typing but the checking happens in compile time, not run time Clueda AG 75 class Cowboy { def shout = "Yehaaw !" }! class Pirate { def shout = "Arrrgh !" }! ! def sayHelloTo( person : { def shout: String} ) = ! ! s"Me : Hello!n $person shouts ${person.shout}" val johnWayne = new Cowboy! ! sayHelloTo(johnWayne)! scala> sayHelloTo(johnWayne)! res4: String =! Me : Hello!! Cowboy@185f8f75 shouts Yehaaw ! val guybrush = new Pirate! ! sayHelloTo(guybrush)! scala> sayHelloTo(guybrush)! res5: String =! Me : Hello!! Pirate@29c356d3 shouts Arrrgh !
  • 76. Pimp-My-Library-Pattern ⬤Add new functions to existing libraries without changing the code! ⬤Like monkey patching! ⬤type safe! ⬤scoped Clueda AG 76
  • 77. Pimp-My-Library-Pattern : Example Source Clueda AG 77 object PimpString {! ! class WeatherString(s: String) {! def ☀ = { println(s"$s sunny!") }! def ☁ = "Dont't forget your ☂!“! }! ! implicit class ♔(name : String) {! def hail = s"Hail to king $name"! }! ! implicit def pimpString(in: String) : WeatherString = ! !new WeatherString(in)! }!
  • 78. Pimp-My-Library-Pattern : Example Usage Clueda AG ⬤Use with caution ! scala> import PimpString._! import PimpString._! ! scala> "Monday is" ☀! Monday is sunny!! ! scala> "???".☁! res8: String = Dont't forget your ☂ scala> val anotherKing = ♔("Louis")! anotherKing: PimpString.♔ = PimpString$$u2654@12359094! ! scala> val aKing = implicitly[♔]("George")! aKing: PimpString.♔ = PimpString$$u2654@5081371! ! scala> aKing.hail! res10: String = Hail to king George 78 scala> val guys = List("James", "Louis", "Franz-Ferdinand")! guys: List[String] = List(James, Louis, Franz-Ferdinand)! ! scala> guys map (_.hail)! res13: List[String] = List(Hail to king James, Hail to king Louis, Hail to king Franz- Ferdinand)
  • 79. Scala - imperative, object oriented, functional Clueda AG 79
  • 80. Scala -imperative, object oriented, functional - Rules of the thumb ⬤functional if possible! ⬤Sometimes imperative is better and faster ! ⬤start out with val and immutable collections,switch to var or mutable collections if needed! ⬤Use object orientation to encapsulate side effects and imperative code Clueda AG 80
  • 81. Advantage of the functional approach ⬤short! ⬤no side effects -> easier to reason about! ⬤composeable Clueda AG 81
  • 82. Advantage of the imperative approach ⬤familiar! ⬤Eventually everything will be iterative after being translated to machine code Clueda AG 82
  • 83. Imperative vs. functional, Examples var i = 0! while (i < args.length) {! if ( i != 0 )! print(" ")! print( args(i) )! i += 1! }! println() Clueda AG 83 Imperative Functional var x = 1! var sum = 0! while (x <= 9999) {! sum += x! x += 1! }! (1 to 9999) foldLeft(0)(_ + _) (1 to 9999) sum println( args mkString " " ) println( ! args reduceOption ( (acc,arg ) => ! acc + " " + arg! )! )
  • 84. Imperative vs. functional, Examples 2 Clueda AG 84 Imperative Functional var i = null! var data = gettingData()! ! if (data != null && data.size > 0) ! ! i = data(0)! else ! ! i = 42! val i = ! ! if (data != null && data.size > 0)! ! ! data(0)! ! else! ! ! 42 val i = ! ! gettingData().headOption getOrElse 42
  • 85. Literatur: ⬤Wampler, D., & Payne, A. (2009). Programming Scala. Sebastopol, CA: O'Reilly.! ⬤Odersky, M., Spoon, L., & Venners, B. (2008). Programming in Scala. Mountain View, Calif: Artima.! ⬤Malayeri, M. “Pimp My Library” Is An Affront To Pimpers Of The World, Everywhere! ⬤http://www.scala-lang.org! ⬤http://www.an-it.com Clueda AG 85
  • 86. Thanks for participating :) Clueda AG 86