scala intro for java devs 20150324
TRANSCRIPT
SCALAAn introduction
What is Scala?• Scala is a multi-paradigm programming language based
on the JVM• It combines Object Orientation (OO) with the principles of
Functional Programming (FP)• Unlike Groovy, it is statically typed, although the syntax is
similar• It’s fully interoperable with Java• It was created by Martin Odersky in 2003, who also
brought Generics to Java.• The name is a Portmanteau for Scalable Langauge (cute)
Scala – a brief historic view
What is Scala?• Interoperability means:
• You can use any Java library within Java• You can compile Scala and Java together in one project• You can use Scala classes and objects from Java
• And coding?• There’s a full support from the most important IDEs, such as
eclipse and IntelliJ• Maven and Gradle have plugins for Scala• Scala’s build tool SBT can also be for Java projects.
What is Scala?• Interoperability means:
• You can use any Java library within Java• You can compile Scala and Java together in one project• You can use Scala classes and objects from Java
• And coding?• There’s a full support from the most important IDEs, such as
eclipse and IntelliJ• Maven and Gradle have plugins for Scala• Scala’s build tool SBT can also be for Java projects.
Language features - classes• Classes in Scala are basically the same as classes in
Java• No primitives – everything is really an object, including the
scala equivalents of void (Unit), byte, short, int long etc…• To achieve this, Scala bridges primitive value classes by
their super class AnyVal, while traditional (‘Java’) objects are represented by their super class AnyRef, which is the equivalent to java.lang.Object. AnyRef and AnyVal both specialize Any.
Language features - objects• Since “static” in Java is quite clunky and inconsistent with
the concept of pure OO, Scala introduces the concept of objects.
• An Object in scala is a singleton instance of a transparent class of a given type.
Companion objects are objects with the same name as a class in the same file. They have private access rights to methods in the class. A common use case for companions are factory methods and conversions.
Language features - traits
Traits are Scala’s interface system – with some differences:• They can be partially implemented, such as Java 8’s default
implementations in interfaces.• They allow safe multiple inheritance while circumventing the
diamond problem (Super class A, B and C inherit from A, D inherits from B and C) -> inheritance of overridden methods is defined by the order of declaration, from left to right using the ‘with’ keyword.
Language features - immutability• In contrast to Java, where members are mutable unless
otherwise specified, Scala propagates immutability by default.
• The obvious reason for defaulting to immutability is safety against race conditions in concurrency.
The val keyword defines immutable variables, basically like final in Java
The var keyword defines mutable variables and should only be used for local scope variables.
Language features - syntax
A main aspect of Scala is Inference – types are derived from their implicit declaration.
scalac – the compiler – will deduce that foo is a String, so there’s no need for an extra declaration. The same thing applies to the colon. It’s optional.
Return is optional too. The last statement of a method, defined by the def keyword is inferred.
val foo : String = „bar“;
val foo = „bar“
def do Foo(bar : String) : String = { „foo“ + bar}
Language features – case classes
Case classes are regular classes which export their constructor parameters and provide support for pattern matching.
This allow pattern matching of the sort expression match case
case class Foo(val bar : String)val bat = Foo(„oof“)Bat.bar will return oof.
val bat = Foo("oof")
bat match { case Foo("bar") => "yeah" case Foo("oof") => "oh no" case _ => "nope"}
Language features - collections
Unlike Java, Scala has two different types of collections: mutable and immutable collections. Both inherit from the same parent trait – Traversable.
The main difference between the two is philosophical. With immutable collections, you either recreate your collection or work with buffers, which you convert, analogous to what you do with StringBuilder and String in Java. Mutable collections behave very much like their Java cousins – Note that Buffers such as ArrayBuffer and ListBuffers are part of the mutable collection family.
Working with Collections
The main difference between collections in Java and in Scala is that collection manipulation is functional, similar to the Stream API in Java 8. Instead of having to iterate through a collection, modify and fill a new collection, scala offers a few nifty methods:
Map:
Filter:
Collect:
val bat = List("dtag", „Xplosion", "im", "google")bat.map( f => f.toUpperCase) // all elements in Uppercase
val bat = List("dtag", „Xplosion", "im", "google")bat.filter( f => Character.isUpperCase(f.charAt(0)) ) // only Xplosion
val strings = bat collect { case s: String => s }val ints = bat collect { case i: Int => i }
Working with Collections – continued..
Partition:
mkString:
flatMap:
Range:
val intList = List(2,7,9,1,6,5,8,2,4,6,2,9,8)val (big,small) = intList partition (_ > 5)
val stringified = big map (s => s + ",") mkStringprintln(stringified dropRight 1) // dropRight removes the last ,
def doSomething(i:Int): Seq[Int] {Seq[Int](i, i*2}val result = small flatMap (i => doSomething(i)} )
val range = 1 to 200 // syntcatic sugar forval range2 = List.range(1,200)
Working with Collections – iterating..
for:
foreach:
yield:
while:
val names = Vector("Bob", "Fred", "Joe", "Julia", "Kim")for (name <- names) println(name)for (name <- names if name.startsWith("J")) // comprehension
val names = Vector("Bob", "Fred", "Joe", "Julia", "Kim")names foreach( s => s + " Dobalina")
val results = for (name <- names) yield (name takeRight 1)println(names) // Vector(Bob, Fred, Joe, Julia, Kim) println(results) // Vector(b, d, e, a, m)
val reader = new DataFileReader[A](...);val results = Seq.newBuilder[A]while (reader.hasNext) { results += reader.next() }results.result
Working with Collections – incrementing..
Mutable Collections:
Immutable Collections:
Maps:
val x = mutable.MutableList(1, 2, 3, 4, 5)x += 6 // like list.add()x ++= mutable.MutableList(7, 8, 9) // like list.addAll()
val y = List(1,2,3,4)val z = 5 :: yprintln(z) // yields List(5, 1, 2, 3, 4)val zz = y ::: List(5)println(zz) // yields List(1, 2, 3, 4, 5)
var states = scala.collection.mutable.Map("AK" -> "Alaska")// add elements with +=states += ("CO" -> "Colorado", “NY" -> “NYC")states -= "KY“ // remove elements with -=states("AK") = "Alaska, The Big State“ // update
Tail recursions
Scala has built-in support for tail recursions. An annotation will ensure that the recursion completes.
val range = 1 to 200
def max(ints: List[Int]): Int = { @tailrec def maxAccum(ints: List[Int], theMax: Int): Int = { if (ints.isEmpty) { return theMax } else { val newMax = if (ints.head > theMax) ints.head else theMax maxAccum(ints.tail, newMax) } } maxAccum(ints, 0)}max(range toList)
Scala Options
Scala has built-in support for optional values, which elegantly circumvents the Null-Billion-Dollar mistake.
def toInt(in: String): Option[Int] = { try { Some(Integer.parseInt(in.trim)) } catch { case e: NumberFormatException => None }}
toInt("154564545") match { case Some(i) => println(i) case None => println("That didn't work.")}
toInt("154564545").getOrElse(0)
Scala - conclusion
Scala’s advantage and at the same time draw back is it’s syntactic sugar. If you stick to a Javaesque style, noboday will complain.
Some concepts such as implicits, bounding and other features are alien, but not necessary
The plus side is the incredible power of FP in a OO setting, which isn’t far from Java shores.