introduction to scala - tu braunschweig · introduction to scala felix geilert. slides will be...
TRANSCRIPT
Scale Out - Modulare Programmiersprache
Scalable Language
Devices – Runs on the JVM
Paradigm – Support for OOP and FP
Full support for Java Libraries
FP Code in Scala is similar to Haskell
Scala was designed with parallelization in mind
Variables and Values
Scala is a strongly typed languageTypes are checked at compile-time
Values
Variablesvar count = 0count = 1
val fix_value = 42
val fix_value2 = “Typesafe!”
Classes• Scala is public by default (there
is no explicit public keyword)
• Constructor is integrated into the definition• Overloading is still possible
• traits can be seen as combination of abstract class and interface
• not allowed to have a constructor, but can be partially implemented
class HelloScala(param: String) {def this = this(“Hello Scala”)def hello = println(param)
}
trait HelloTrait {def hellodef greet = println(“Wad up?”)
}class HelloScala(param: String) implements HelloTrait {
def this = this(“Hello Scala”)def hello = println(param)
}
• def keyword is used to define functions
• traits are mix-ins: They can implement functions and a class can be a mix of multiple traits!
Objects
aka Singleton made easy
object MySingleton {def someNumber: Int = {
println(“a cool number”)42
}}
println(MySingleton.someNumber)
• Defines an object which provides static functions
• Therefore there will always only be one instance
• Scala returns the expression in the last line. No explicit return needed!
Objects
also a good companion
• Basically holds all static methods• Can be used to implement the factory
pattern
class HelloScala(param: String) {def this = this(“Hello Scala”)def hello = println(param)
}
object HelloScala {def create: HelloScala = HelloScala(“Singleton”)
}
Applications
object HelloScala {def main(args: Array[String]) {
println(“Hello”)}
}
class HelloScala extends App {println(“Short Hello”)
}
Main Method – Java Style
Main Method – Scala Style
We use object here, to make the method static
Take Home Points
Scala is type safe – All types are checked at compile time
var/val to create variables and constants
Singletons can be created using objects
Traits are a mix of abstract class and interface
They can define which type can implement them (self-trait)
Why should we use Scala?
Boilerplate
No Semicolons App instead of main method
Singletons made easy Typesafe – Less Error Prone
Packages are not restricted to foldersNo explicit return
And the list goes on…
Remember Maven?
And all the fun you had creating those XML’s?
Simple Built Tool
name := “HelloScala”
scalaVersion := “2.11.4”
version := “1.0-SNAPSHOT”
val akkaV := “2.3.4”
libraryDependencies ++= Seq(“com.typesafe.akka” %% “akka-actor” % akkaV,“com.typesafe.akka” %% “akka-remote” % akkaV,“com.typesafe.akka” %% “akka-cluster” % akkaV
)
• define project name
• define Version of Scala. SBT will load it, so it does not have to be installed
• some library dependencies. You can use maven repositories here!
Functional Programming
Pure Functions
Based on pure functions
No Side-Effects
Referential Transparency
Everything that leaves the function
Side-Effect =
No Global StateFunctions only depend on their input parameters
Therefore it does not matter in which order functions are executed
Pure Functions
A small Example
var counter = 0
def increaseNumber(x: Int): Int = {if (counter < 100) {
println(“get a new number”)counter = counter + 1x + counter
}else
throw new Exception(“too high”)}
val num1 = increaseNumber(10) // will be 11val num2 = increaseNumber(5) // will be 7
Global State!
val num2 = increaseNumber(5) // will be 6val num1 = increaseNumber(10) // will be 12
No Referential Transparancy!
Pure Functions
A small Example
def increaseNumber(x: Int, counter: Int): (Int, Int) = {if (counter < 100) {
println(“get a new number”)(x + counter + 1, counter + 1)
}else
throw new Exception(“too high”)}
val num1, c1 = increaseNumber(10, 0) // will be 11val num2, c2 = increaseNumber(5, 1) // will be 7
Side-Effects
Scala does have integrated Tuple Types!
Pure Functions
A small Example
def increaseNumber(x: Int, counter: Int): Option[(Int, Int)] = {if (counter < 100) {
Some( (x + counter + 1, counter + 1) )}else
None}
val num1Opt = increaseNumber(10, 0) // will be 11val (num1, c1) = num1Opt.getOrElse( (0,0) )val num2Opt = increaseNumber(5, 1) // will be 7val (num2, c2) = num2Opt.getOrElse( (0,0) )
Option-MonadeCan have 2 types:Some with embedded valueNone
Split tuple in values
ListsQuite like Haskell
Recursive Data-Structure
sealed trait List[+A]case object Nil extends List[Nothing]case class List[+A](head: A, tail: List[A]) extends List[A]
val ls1 = List()= Nil
val ls2 = List(1)= List(1, Nil)
val ls3 = List(1,2,3,4)= List(1,List(2,List(3, List(4, Nil))))
Nothing is the Subclass of everything
Pattern Matching
val ls = List(1,2,3,4)
ls match {case head :: Nil => println(“The last of it’s kind!”)case head :: tail if head == 4 => println(“It is a four!”)case head :: tail => println(s“It is a $head”)case Nil => println(“There is nothing here.”)
}
Order is important. This will not be matched if it stands after head::tail
There can be additional conditions attached to the cases
Case Classes
case class Person(name: String, age: Int)
Advantage: Can easily be constructed and destructed!Also it is easy to transform them into a string (and compare them)
val p1 = Person(“Lawyer”, 42)println(p1)
Output: Person(Lawyer, 42)
Why do we need that?
Case ClassesPattern matching
Apply/Unapplyval p1 = Person(“John Doe”, 42)p1 match {
case p: Person => p.namecase _ => “Unknown”
}
p1 match {case Person(name, age) => namecase _ => “Unknown”
}
Easy to construct / deconstruct classes
Person.apply(“John Doe”, 42)
Person.unapply(p1) : Option[(String, Int)]
p1 match {case Person(name, age) if age > 42 => namecase _ => “Unknown”
}
Partial Functions
Functions that are not defined for all possible input values
Partial Functions are used all over ScalaList(1,2,3) foreach {
case x: Int => println(x)}
def fraction(value: Int) = 10 / value
Obviously not defined for value = 0
val fraction: PartialFunction[Int, Int] = {case value if value != 0 => 10 / value
}
List(1,2,3) map {case x: Int => x + 1
}
try {//code…
}catch {
case e: IOException => println(“oh no”)}
List(1,2,3) match {case head :: tail => println(head)
}
Recursion
Recursion through Lists on the base of Partial Functions
def filter(ls: List[Int], value: Int): List[Int] = {@annotation.tailrecdef loop(ls_in: List[Int], ls_out: List[Int]): List[Int] = ls_in match {
case head :: tail if head == value => loop(tail, ls_out)case head :: tail => loop(tail, ls_out :+ head)case Nil => ls_out
}
loop(ls, List())}
Inner Function
Tail Recursive Function calls
Call in the outer function
Comprehensions
Comprehensions are generalized for loops
for (enumerations) yield {codeblock}
Codeblock will be evaluated for each possibility in the enumerations. It returns a sequence of the
results of the codeblock
val ls1 = List(1,2,3)val ls2 = List(“a”, “b”, “c”)
val ls3 = for (i <- ls1, j <- ls2) yield (i,j)
Generate a tuple for each possible combination
Output: List((1,a), (1,b), (1,c), (2,a), (2,b), (2,c), (3,a), (3,b), (3,c))
implicitsUnique to Scala
Based on type safety: allows to create functions for specific types that are used implicitly
case class Person(name: String, age: Int)
implicit def convertPerson(name: String) : Person = Person(name, 42)
def showPerson(p: Person) = println(p)
showPerson(“John Doe”)
• Compiler detects, that type string is given buttype person required
• Also know that there is a function he isallowed to use implicitly to convert a stringinto a person
As a result, each implicit conversion has to be unique in terms of types!
Duck typing / Structural Subtyping
Idea: define a parameter by the functions it has, not by the type
def duckTyping(input: {def quack(value: String): String} ) = println(duck.quack(“Hello Scala”))
Input can be anything that has a quack function with the given signature
val x = new AnyRef {def quack(value: String): String = “I AM ” + value
}duckTyping(x)
object Duck {def quack(value: String): String = “simple ” + value
}duckTyping(Duck)
AnyRef is the highest class in Scala HierarchyIt stands for anything
Lazy EvaluationHaskell is always lazy
Scala has specific keyword for that
Specifies when an expression is evaluated
def defTest = {println(“def test”)42
}
val valTest = {println(“val test”)42
}
lazy val lazyTest = {println(“lazy test”)42
}
defTestOutput:def test42
val test
valTestOutput:42
lazyTestOutput:lazy test42
lazyTestOutput:42
Scala vs Java
Scala generalizes almost anything
Interfaces Traits
Switch-Case Pattern Matching
Singleton Pattern Objects
Loops Comprehensions
Scala vs Java
Scala has some features that do not exist in Java
Implicits Duck Typing
Lazy Evaluation Self Trait
Case Classes Partial Functions
And there is more…
Macros Immutable Collections
Scala vs Java
Scala allows to easily create DSL (Domain Specific Languages)This allows you to add new elements to the languageYou miss something in the language? Add it yourself!
“My Class” should “double a number” in {MyClass.double(4) should be (8)
}
ScalaTest – DSL to create unit tests