1. Scala for Java Developers
Mohsen Zainalpour
zainalpour@yahoo.com
2. Goals
• Have an understanding of what Scala is
• Have an interest in learning more
• Go install Scala!
3. What is Scala?
• A general purpose programming language
• A language that runs on the Java VM
• Statically typed
• An object-oriented language
• No primitives or operators, but with singletons
• A functional language
• A scalable language
• Java compatible
4. Scala History … 1995 to 2013
Brief history of Scala
•Developed by Martin Odersky
o 1995 he learned of Java and wrote functional language that compiled to Java
bytecode - Pizza
o Pizza evolved into what we now recognize as Java generics
•Sun approached Odersky in 1997 to write Java 1.1 compiler
•Odersky led javac development from Java 1.1 through 1.4
•In 1999, Odersky joined EPFL to conduct research into
improving functional and OO languages
•Design of Scala began in 2001 and first release was in 2003
•Early releases of compiler written in Java
•Version 2.0.0 introduced a completely rewritten compiler in Scala
•Current version 2.10.1 released in March 2013
5. Is Scala a fit?
• Core Strengths
o Functional Programming
o Less boilerplate code
o Concurrency
o Java Interoperable
o Domain-Specific Languages
o XML
o Bridging
• Weaknesses
o Syntax
o Mutability
6. Getting up and running
Required
•Java 1.5 or greater
•Scala 2.10.1 distribution
Optional
•SBT – Simple Build Tool
•IDE Plugin
o ScalaIDE (Eclipse – must use Helios)
o Scala Plugin for IntelliJ IDEA
o Scala Plugin for NetBeans
8. Definitions
Scala method definitions: Java method definition:
def fun(x: Int): Int = { int fun(int x) {
result return result
} }
def fun = result (no parameterless methods) Java
Scala variable definitions: variable definitions:
var x: Int = 10 int x = 10
val y: String = "Scala" final String x = "Scala"
9. Objects and Classes
Scala Class and Object Java Class with statics
class Sample(x: Int, val p: Int) { public class Sample {
def instMeth(y: Int) = x + y private final int x;
} public final int p;
object Sample { Sample(int x, int p) {
def staticMeth(x: Int, y: Int) = x * y this.x = x;
} this.p = p;
}
int instMeth(int y) {
return x + y;
}
static int staticMeth(int x, int y) {
return x * y;
}
}
10. Traits
Scala Trait Java Interface
trait T { interface T {
var field = "!" int abstractMth(String x)
}
def abstractMth(x: String): Int
(no concrete methods) (no fields)
def concreteMth(x: String) = x +
field Java extension + implementation:
}
class C extends Super implements T
Scala mixin composition:
class C extends Super with T
11. Constructors
class Person(val firstName: String, val lastName: String) {
private var position: String = _
println("Creating " + toString())
def this(firstName: String, lastName: String, positionHeld: String) {
this(firstName, lastName)
position = positionHeld
}
override def toString(): String = {
firstName + " " + lastName + " holds " + position + " position "
}
}
12. Statics in Scala
class Marker private(val color: String) {
override def toString(): String = "marker co1or " + color
}
object Marker {
private val markers = Map(
"red" -> new Marker("red"),
"b1ue" -> new Marker("blue"),
"green" -> new Marker("green")
)
def primaryColors = "red, green, blue"
def apply(color: String) = if (markers.contains(color)) markers(color) else null
}
object MarkerTest extends App {
println("Primary co1ors are · " + Marker.primaryColors)
println(Marker("blue"))
println(Marker("red"))
}
13. Higher Order Functions
These are functions that take other functions as
parameters, or whose result is a function.
class Decorator(left: String, right: String) {
def layout[A](x: A) = left + x.toString() + right
}
object FunTest extends App {
def apply(f: Int => String, v: Int) = f(v)
val decorator = new Decorator("[", "]")
println(apply(decorator.layout, 7))
}
14. Currying & Partial
Functions
Methods may define multiple parameter lists. When a method is called with a fewer number of parameter
lists, then this will yield a function taking the missing parameter lists as its arguments.
object CurryTest extends App {
def filter(xs: List[Int], p: Int => Boolean): List[Int] =
if (xs.isEmpty) xs
else if (p(xs.head))
xs.head :: filter(xs.tail, p)
else filter(xs.tail, p)
def modN(n: Int)(x: Int) = ((x % n) == 0)
val nums = List(1, 2, 3, 4, 5, 6, 7, 8)
println(filter(nums, modN(2)))
println(filter(nums, modN(3)))
}
15. Closures
You can create code blocks with variables that are not bound.
You will have to bind them before you can invoke the function; however,
they could bind to, or close over, variables outside of their local scope
and parameter list.
That’s why they’re called closures.
•A closure allows a function to access variables outside its immediate lexical
scope.
Val outer:String=“scala”
Val f:( String => Unit) = { (x:String) => println(x + “ “ + outer)
16. Traits
They are fundamental unit for code reuse in Scala
A Trait encapsulates method and field definitions, which can be
reused by mixing them in classes
Unlike class inheritance , in which class must inherit from just one
superclass, a class may mix in any number of Traits
Unlike Interfaces they can have concrete methods
17. import scala.collection.mutable.ArrayBuffer //Mixing traits in type definition
class DoublePlusOneQueue extends IntQueueImpl with
//Type Definition Incrementing with Doubling
abstract class IntQueue {
def get(): Int object QueueWithTraits {
def main(args: Array[String]) {
def put(x: Int) val queue1 = new DoublePlusOneQueue
queue1 put 1
def size(): Int queue1 put 2
} println(queue1 get)
println(queue1 get)
//ArrayBuffer implementation
class IntQueueImpl extends IntQueue { //Mixing traits in object instantiation
private val buf = new ArrayBuffer[Int] val queue2 = new IntQueueImpl with Filtering
queue2 put -1
def get = buf remove 0 queue2 put 1
println(queue2 size)
def put(x: Int) { }
buf += x }
}
def size = buf length
}
trait Doubling extends IntQueue {
abstract override def put(x: Int) {
super.put(2 * x)
}
}
trait Incrementing extends IntQueue {
abstract override def put(x: Int) {
super.put(x + 1)
}
}
trait Filtering extends IntQueue {
abstract override def put(x: Int) {
if (x > 0) super.put(x)
}
}
18. Pattern Matching
Scala has a built-in general pattern matching mechanism. It
allows to match on any sort of data with a first-match policy.
object MatchTest2 extends App {
def matchTest(x: Any): Any = x match {
case 1 => "one"
case "two" => 2
case y: Int => "scala.Int"
}
println(matchTest("two"))
println(matchTest(100))
}
24. Functional programming
• The functional paradigm expresses programs as
functions in the mathematical sense, mapping from
one value to another (f (x) = y)
• without side effects, such as :
o maintaining the status of objects
o input/output of data
• Features such as :
o immutable values
o collections
o higher-order functions
o pattern matching
encourages Scala developers to use the functional style.
25. a program that prints the thousandth element of the Fibonacci sequence can be written as
follows in Java:
import java.math.BigInteger;
public class FiboJava {
private static BigInteger fibo(int x) {
BigInteger a = BigInteger.ZERO;
BigInteger b = BigInteger.ONE;
BigInteger c = BigInteger.ZERO;
for (int i = 0; i < x; i++) {
c = a.add(b);
a = b;
b = c;
}
return a;
}
public static void main(String args[]) {
System.out.println(fibo(1000));
}
}
26. a more compact and functional version, using infinite
sequences and tuples can be very different:
import scala.math.BigInt
object Main extends App {
val fibs: Stream[BigInt] =
BigInt(0) #:: BigInt(1) #:: fibs.zip(fibs.tail).map {
n => n._1 + n._2
}
fibs take 5 foreach println
}
27. java 8 Lambda project
Lambda Expressions as Functions
•A lambda expression is a function literal. It defines a function with input parameters and function body.
(String s1, String s2) -> s1.length() - s2.length();
Lambda Expression as Closures
•A closure allows a function to access variables outside its immediate lexical scope.
String outer = "Java 8" (String s1) -> s1.length() - outer.length()
Hello Lambda Expressions, Goodbye Anonymous Inner Classes
class UIBuilder {
public UIBuilder() {
button.addActionListener(e -> //process ActionEvent e)
}
}
Higher-Order Functions as Reusable Building Blocks
When we pass a function literal to a method, we basically have a method that accepts a method. Such methods are
called higher-order functions.
def measure[T](func: => T):T = { val start = System.nanoTime() val result = func val elapsed =
System.nanoTime() - start println("The execution of this call took: %s ns".format(elapsed)) result }
def myCallback = { Thread.sleep(1000) "I just took a powernap" } val result = measure(myCallback);
28. Less boilerplate code
Some Scala features, such as :
• type inference
• unchecked exceptions
• optional objects
• implicit conversions
can greatly reduce the amount of statements and checks in a program, without
changing its meaning.
29. In Java:
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Collections;
import java.util.Enumeration;
public class ListMACsJava {
public static void main(String[] args) throws SocketException {
Enumeration<NetworkInterface> nics =
NetworkInterface.getNetworkInterfaces();
for (NetworkInterface nic : Collections.list(nics)) {
byte[] mac = nic.getHardwareAddress();
for (int i = 0; mac != null && i < mac.length; i++) {
System.out.format("%2x", mac[i]);
System.out.print(i == mac.length - 1 ? 'n' : ':');
}
}
}
}
31. Or, another implementation in Scala using sequence
comprehension :
import java.net.NetworkInterface
import scala.collection.JavaConversions._
object ListMACsScala {
def main(args: Array[String]) {
val nicaddresses = for {
nic <- NetworkInterface.getNetworkInterfaces
addrbytes <- Option(nic.getHardwareAddress)
} yield {
addrbytes map {
"%02x" format _
} mkString ":"
}
nicaddresses foreach println
}
}
32. Does Scala offer better concurrency?
“If it hurts, stop doing it” is a doctor’s good advice. In
concurrent program-ming, shared mutability is “it.”
Shared mutability—the root of concurrency roblems—
is where multiple threads can modify a variable.
Solution :
•Immutability
•Actors
33. Immutability
• Synchronizing access to shared mutable objects
can result in much complexity in the use of
concurrency primitive (locks, semaphores, etc.).
• Scala tries to mitigate this problem by using
immutable objects and pure functions
• If an object is immutable, it can be shared or
copied without worrying about who is using it, so it is
naturally "thread-safe."
34. Actors
• Using Low-level parallelism controls, such as locks
and synchronized blocks may not be easy.
• to write this type of program more productively and
prevent defects, a high level concurrency control is
very desirable.
Such abstraction can be like
o Fork /Join
o Software Transactional Memory
o or, as featured in Scala, the Actor Model.
In Actor Model, the parallelism is expressed as actors reacting to messages,
rather than locking and releasing of threads.
37. The following example demonstrates actors estimating the value of Pi using the Monte Carlo method.
import scala.util.Random
import Math._
import scala.actors.Actor
case object Calculate
case object ShutDown
class Calculator extends Actor {
val rand = new Random
var in, cnt = 1.0
def act {
while (true) {
receive {
case Calculate =>
sender ! estimativeOfPi
case ShutDown => exit
}
}
}
def estimativeOfPi: Double = {
val x = rand.nextDouble - 0.5
val y = rand.nextDouble - 0.5
cnt += 1.0
if (sqrt(x * x + y * y) < 0.5) in += 1
in / cnt * 4
}
}
38. The "coordinator" starts a list of calculators and tell them to calculate until any of them produces an accurate enough estimation
import actors.Actor
class Coordinator(numOfCalculators: Int) extends Actor {
def act {
val startedAt = System.currentTimeMillis()
var calculators = List.fill(numOfCalculators)(new Calculator)
calculators.foreach(c => {
c.start
c ! Calculate
})
while (true) {
receive {
case estimative: Double =>
val error = Math.abs(Math.PI - estimative)
if (error > 0.0000001)
sender ! Calculate
else {
val tempo = System.currentTimeMillis() - startedAt
calculators.foreach(_ ! ShutDown)
println("Pi found by " + sender + " = " + estimative)
println("Execution time: " + tempo)
exit
}
}
}
}
}
object PiActors extends App {
new Coordinator(2) start
}
39. Parallel Collections
Scala 2.9 introduced parallel collections, which makes it easy to parallelize the
execution of common collections operations, such as map(), filter () and
foreach(). The par() method can be used to obtain a parallel version of the
collection
object ParCol extends App {
(1 to 5) foreach println
(1 to 5).par foreach println
}
40. XML
An interesting combination in Scala is the XML syntax in combination
with pattern matching.
val movies = <movies>
<movie>The Incredibles</movie>
<movie>WALL E</movie>
<short>Jack Jack Attack</short>
<short>Geri's Game</short>
</movies>
(movies "_").foreach {
movie =>
movie match {
case <movie>{movieName}</movie> => println(movieName)
case <short>{shortName}</short> => println(shortName + " (short)")
}
}
41. Is Scala extensible?
Scala allows developers to customize the look and
feel of the language, creating new languages and
altering the compilation process.
42. Domain Specific Languages
Using generic classes, abstract types, functions as objects, methods named as
operators and implicit conversions, Scala code can become a domain specific
language (DSL).
Domain-specific languages can also be created when a more abstract and
declarative language is needed by developers. For example, Apache Camel offers a
Scala DSL to make the configuration of service routes more concise and correct.
"direct:a" ==> {
to ("mock:polyglot")
choice {
when (_.in == "<hello/>") to ("mock:english")
when (_.in == "<hallo/>") {
to ("mock:dutch")
to ("mock:german")
}
otherwise to ("mock:french")
}
}
43. Changing the compilation
• allowing the creation of entirely new grammars with
parser combinators.
• create compiler plugins to change the build
process.
These plugins could be written, for :
operform static code analysis .
oevaluating metrics, like PMD or FindBugs.
44. Are Scala and Java
interoperable?
• it is possible to invoke Java methods in Scala code and
vice versa.
• When calling Scala methods from Java, the developer
needs to understand how the features that do not exist
in Java. For example:
o methods with non-alphabetic names
o receiving functions
o tuples as parameters
• When invoking Java from Scala, the problems is the
features of Java that were abandoned or implemented
differently in Scala, such as :
o interfaces
o annotations
o collections
45. Using Java Libraries and
Frameworks in Scala
any library or framework available for Java can be used in Scala. This includes all Java
EE (EJB, JSF, JAX-RS, etc.) and popular libraries, such as Hibernate and Junit.
import javax.servlet.http._
import javax.servlet.annotation.WebServlet
import scala.collection.JavaConversions._
@WebServlet(Array("/printParams"))
class PrintParametersServlet extends HttpServlet {
override def
doGet(req:HttpServletRequest, resp:HttpServletResponse) {
val out = resp.getWriter req.getParameterMap.map {
case (key,value)=>key + " = " + value.mkString(",")
}.foreach(out println _)
}
}
46. Final Thoughts
Scala is appropriate for an application that has
significant scalability requirements that requires
concurrency