(how) can we benefit from adopting scala?

69
(How) Can we benefit from adopting Scala ? Tomasz Wróbel, 2011-01-24

Upload: tomasz-wrobel

Post on 10-May-2015

1.595 views

Category:

Technology


3 download

TRANSCRIPT

Page 1: (How) can we benefit from adopting scala?

(How) Can we benefitfrom

adoptingScala

?

Tomasz Wróbel, 2011-01-24

Page 2: (How) can we benefit from adopting scala?

in other words what Scala has to offer

Page 3: (How) can we benefit from adopting scala?

Few quick facts

• Strong typing• Static typing• Can be both interpreted and compiled into

bytecode and run on top of a JVM (among others)

• Interoperability with Java• No primitive types – everything is an object

Page 4: (How) can we benefit from adopting scala?

Productivity gain

• Concise, expressive → achieve more with less• Reduced boilerplate code – semicolons, dots,

parentheses, return – these are often optional (depending on the context)

• Extensive type inference• ½ LOC at least• Code is read more frequently than written

Page 5: (How) can we benefit from adopting scala?

Support for both functional andobject-oriented programming paradigms

• Code blocks (anonymous functions)• Higher-order functions (ones that produce or

consume functions)• Closures• Sophisticated collection library

Page 6: (How) can we benefit from adopting scala?

REPL

Read-Evaluate-Print Loop

scala> val s = "Hello!"

s: java.lang.String = Hello!

scala> println(s)

Hello!

Page 7: (How) can we benefit from adopting scala?

REPL:help print this help message

:load <arg> load and interpret a Scala file

:sh <line> fork a shell and run a command

scala> :sh ls

stdout: List[String] = List(Desktop, Documents, Downloads, Library, Movies, Music, Pictures, Public, Sites)

Page 8: (How) can we benefit from adopting scala?

How difficult is it to switch?Java → Scala

// class

public class A {}

// variable

private int i = 0;

// function

public String fun(String s) {

return s;

}

class A {}

private var i: Int = 0;

def fun(s: String): String = {

return s;

}

Page 9: (How) can we benefit from adopting scala?

Variables

• everything is either val or var• val – immutable• var – mutable

val x: Int = 1; x = x + 1

var y = 1; y = y + 1

val set = new java.util.HashSet[String]

set.add("abc")

Page 10: (How) can we benefit from adopting scala?

Type inferenceval i: Int = 1

def upper(s: String): String = s.toUpperCase

val list: List[Int] = List[Int](1,2,3)

note: there are situations where type is required, e.g. recursive methods

Page 11: (How) can we benefit from adopting scala?

operators = functions

• 1 + 2 is actually (1).+(2)• operators overloading• possibility to define new data types

Page 12: (How) can we benefit from adopting scala?

Eurocase class Euro(euros: Int, cents: Int = 0) {

def +(e: Euro) = Euro(

euros + e.euros + ((cents + e.cents) / 100),

(cents + e.cents) % 100

)

}

case class Cent(cents: Int)

assertThat(Euro(5) + Euro(5), is(Euro(10)))

assertThat(Euro(4) + Cent(99), is(Euro(4, 99)))

Page 13: (How) can we benefit from adopting scala?

Rangesval oneToTen = 1 to 10

assertThat(oneToTen.size, is(10))

val evenNumbers = 2 to 10 by 2

assertThat(evenNumbers.size, is(5))

val alphabet = 'a' to 'z'

assertThat(alphabet.size, is(26))

Page 14: (How) can we benefit from adopting scala?

Tuples

are typedscala> val tuple = ("CODE", 31)

tuple: (java.lang.String, Int) = (CODE,31)

Page 15: (How) can we benefit from adopting scala?

Tuples

are convenient way to return multiple values from a function

def analyzeString(s: String): (String, Int) = {

(s.toUpperCase, s.length)

}

scala> val result = analyzeString("abc")

result: (String, Int) = (ABC,3)

Page 16: (How) can we benefit from adopting scala?

Controlling executionsfor (i <- 0 to 9) {

print(i)

}

for (i <- 0 to 9) {

if (i % 2 == 0) println("even: " + i) else println("odd: " + i)

}

Page 17: (How) can we benefit from adopting scala?

Controlling executionsvar i = 0

while (i < 10) {

print(i)

i += 1

}

Page 18: (How) can we benefit from adopting scala?

Raw strings// given

val s = """|first line

|second "B" line

|third line""".stripMargin

// then

assertThat(s, is("first line\nsecond \"B\" line\nthird line"))

Page 19: (How) can we benefit from adopting scala?

Raw stringsassertThat("1234".matches("""\d*"""), is(true))

assertThat("12ab".matches("""\d*"""), is(false))

new File("""c:\some\path\to\file.txt""").exists

Page 20: (How) can we benefit from adopting scala?

Making assertions@Test(expected = classOf[IllegalArgumentException])

def convenientAssertions {

val i = -1

require(i > 0)

}

Page 21: (How) can we benefit from adopting scala?

Objects equality

• == is Java's equals()• eq()is Java's ==

Page 22: (How) can we benefit from adopting scala?

Importsimport java.util.Date

import java.text.{DateFormat, SimpleDateFormat}

import java.math._

// static imports

import java.util.Arrays.asList

import java.util.Collections._

// aliasing

import java.sql.{Date => SqlDate}

Page 23: (How) can we benefit from adopting scala?

Tail recursion

compiler optimizes tail-recursive functions to loops → preventing stack overflow errors

@tailrec

final def fact(n: Int, acc: Long = 1): Long = {

if (n < 1) acc else fact(n - 1, n * acc)

}

@tailrec – optional, compiler hints you if on not tail-recursive function

Page 24: (How) can we benefit from adopting scala?

There is always an Optioni.e. null alternative

scala> def map = Map("PL" -> "Poland")

scala> val country: Option[String] = map.get("PL")

country: Option[String] = Some(Poland)

scala> val res = country.get

res: String = Poland

scala> val res = country.getOrElse("default")

res: String = Poland

scala> val country: Option[String] = map.get("UK")

country: Option[String] = None

scala> val res = country.getOrElse("default")

res: String = default

scala> val res = country.get

java.util.NoSuchElementException: None.get

Page 25: (How) can we benefit from adopting scala?

Implicits

Allow to add functionality to existing classesval past = 2 days ago // 2.days(ago)

val future = 5 days later // 5.days(later)

println(new java.util.Date)

println(past)

println(future)

Sun Jan 23 22:18:51 GMT 2011

Fri Jan 21 22:18:51 GMT 2011

Fri Jan 28 22:18:51 GMT 2011

Page 26: (How) can we benefit from adopting scala?

class, object, trait

• class – holds instance methods and fields• object – companion object – singleton

object, holds class (static) methods• trait – partial class implementation or

interface with implementation, it is possible to mixin multiple traits

Page 27: (How) can we benefit from adopting scala?

class and objectclass Article private(title: String)

object Article {

def newInstance(title: String) = new Article(title)

}

object App {

def main(args: Array[String]) {

val article = Article.newInstance("a Title")

}

}

Page 28: (How) can we benefit from adopting scala?

Traitstrait SingleJournalRelease extends PressRelease {

override def validate = println("articles form the same journal")

}

trait IssueRelease extends PressRelease {

override def header = print("Issue Press Release containing ")

}

trait AopRelease extends PressRelease {

override def header = print("AOP Press Release containing ")

}

class AcademicJournalAopPressRelease extends AopRelease with SingleJournalRelease

class ResearchJournalIssuePressRelease extends IssueRelease with SingleJournalRelease

Page 29: (How) can we benefit from adopting scala?

Anonymous functionsval list = List(1, 2, 3)

val odds = list.filter((each: Int) => each % 2 != 0)

assertThat(odds, is(List(1, 3)))

Page 30: (How) can we benefit from adopting scala?

Functions

Functions can be assigned to variables and be passed as parameters

val complicatedProcessing = (s: String) => s.toUpperCase

assertThat(complicatedProcessing("abc"), is("ABC"))

val list = List("a", "b", "c")

val result = list.map(complicatedProcessing)

assertThat(result, is(List("A", "B", "C")))

Page 31: (How) can we benefit from adopting scala?

Local functions

Functions can be nested

def outer {

def inner(s: String) = println("inner " + s)

inner("outer")

}

Page 32: (How) can we benefit from adopting scala?

Passing parameters to functionsscala> def fun(s: String) = println(s)

fun: (s: String)Unit

scala> fun("abc")

abc

scala> fun{"abc"}

abc

Page 33: (How) can we benefit from adopting scala?

Curried functions

Currying = turning a function that takes two arguments into a chain of functions that take one argument

def sum(x: Int, y: Int) = x + y

def multiple(x: Int)(y: Int) = x * y

scala> val result = sum(1, 2)

result: Int = 3

scala> val result = multiple(1)(2)

result: Int = 2

Page 34: (How) can we benefit from adopting scala?

Adding new control structureswriteToFile("output.txt") {

writer => writer.println("abc")

}

def writeToFile(fileName: String)(block : PrintWriter => Unit) = {

val writer = new PrintWriter(new File(fileName))

try { block(writer) } finally writer.close()

}

Page 35: (How) can we benefit from adopting scala?

Implementing unlessscala> def unless(cond: => Boolean)(body: => Unit): Unit =

| if (!cond) {

| body

| }

unless: (cond: => Boolean)(body: => Unit)Unit

scala> unless(1 > 2) {

| print("1 is not greater than 2")

| }

1 is not greater than 2

Page 36: (How) can we benefit from adopting scala?

Closures// given

val base = 100

def closeAroundBase(i: Int) = {

i + base

}

// then

assertThat(closeAroundBase(10), is(110))

Page 37: (How) can we benefit from adopting scala?

Why is closure useful?val patternProvidedByUser = "L.*"

val data = List("London", "Oxford", "Leeds")

val result = data.filter(_.matches(patternProvidedByUser))

result: List[java.lang.String] = List(London, Leeds)

Page 38: (How) can we benefit from adopting scala?

Case classescase class Article(var doi: String, var title: String)

// Provide convenient factory method

val article = Article("10.1038/nature01234", "a Title")

// and implementations for

assertThat("toString", article.toString, is("Article(10.1038/nature01234,a Title)"))

assertThat("hashCode", article.hashCode, equalTo( equalArticle.hashCode ))

assertTrue("equals", article == equalArticle)

Page 39: (How) can we benefit from adopting scala?

Pattern matching

• match as switch on steroids• always results in a value• no “fall through”• MatchError thrown if no match• _ is default

Page 40: (How) can we benefit from adopting scala?

Matching by constantdef fun(o: Any): Int = o match {

case "abc" => 1

case 1 => 2

case Nil => 0

}

Page 41: (How) can we benefit from adopting scala?

Matching by type(no more instanceof and casting)

def size(o: Any): Int = o match {

case s: String => s.length

case l: List[_] => l.size

case _ => -1

}

assertThat(size("abc"), is(3))

assertThat(size(List(1, 2)), is(2))

Page 42: (How) can we benefit from adopting scala?

Matching by tupledef fun(o: Any): Any = o match {

case (a: Int, b: Int) => a + b

}

Page 43: (How) can we benefit from adopting scala?

Matching by constructorcase class Rectangle(a: Int, b: Int)

def identify(r: Rectangle): String = r match {

case Rectangle(2, 4) => "2x4"

case Rectangle(a, b) if a == b => "Square" // pattern guard

case Rectangle(a, b) => "Rectangle " + a + "x" + b

}

assertThat(identify(Rectangle(2, 4)), is("2x4"))

assertThat(identify(Rectangle(1, 1)), is("Square"))

assertThat(identify(Rectangle(1, 2)), is("Rectangle 1x2"))

Page 44: (How) can we benefit from adopting scala?

(optional) Exception handling try {

val f = new FileInputStream("file.txt")

} catch {

case e: IOException => // handle the exception

}

but can be also just:

val f = new FileInputStream("file.txt")

Page 45: (How) can we benefit from adopting scala?

Named and default parameterscase class Article(id: Int, doi: String, title:

String)

def make(id: Int = 1, doi: String = "a Doi", title: String = "a Title") = {

Article(id, doi, title)

}

Page 46: (How) can we benefit from adopting scala?

Named and default parametersDefaulting omitted parameter(s)

val article = make(99, "10.1038/nature01234")

assertThat(article.id, is(99))

assertThat(article.doi, is("10.1038/nature01234"))

assertThat(article.title, is("a Title"))

Page 47: (How) can we benefit from adopting scala?

Named and default parametersSetting parameter by name

val article = make(doi = "10.1038/nature01234")

assertThat(article.id, is(1)) // default

assertThat(article.doi, is("10.1038/nature01234"))

assertThat(article.title, is("a Title")) // default

Page 48: (How) can we benefit from adopting scala?

CollectionsEasy construction

val aList = List(1, 2, 3)

val aMap = Map("A" -> 1, "B" -> 2, "C" -> 3)

val aSet = Set("a", "b", "c", "b", "a")

scala> val list = List(1) ::: List(2) // concatenate

list: List[Int] = List(1, 2)

scala> val list = List(1) ++ List(2) // concatenate

list: List[Int] = List(1, 2)

scala> val list = 1 :: List(2) // add element (as a first one)

list: List[Int] = List(1, 2)

Page 49: (How) can we benefit from adopting scala?

CollectionsIterable - a base trait for iterable collections with ~100 functions

scala> val numbers = List(1, 2, 3, 4, 5)

scala> val negatives = numbers.map(e => -e)

negatives: List[Int] = List(-1, -2, -3, -4, -5)

scala> val even = numbers.filter(n => n % 2 == 0)

even: List[Int] = List(2, 4)

scala> val (even, odd) = numbers.partition(_ % 2 == 0)

even: List[Int] = List(2, 4)

odd: List[Int] = List(1, 3, 5)

Page 50: (How) can we benefit from adopting scala?

Collectionsscala> val result = numbers.mkString(", ")

result: String = 1, 2, 3, 4, 5

scala> val result = numbers.count(_ > 2)

result: Int = 3

scala> numbers.foreach(print _)

12345

Page 51: (How) can we benefit from adopting scala?

CollectionsExample for groupBy

scala> case class Article(journal: String, doi: String)

scala> val articles = List(Article("NATURE", "nature09733"), Article("NMAT", "nmat2937"), Article("NMAT", "nmat1807"), Article("NPHYS", "nphys1906"))

scala> val result = articles.groupBy(e => e.journal)

scala> val nmat = result("NMAT")

nmat: List[Article] = List(Article(NMAT,nmat2937), Article(NMAT,nmat1807))

scala> val nature = result("NATURE")

nature: List[Article] = List(Article(NATURE,nature09733))

scala> val nphys = result("NPHYS")

nphys: List[Article] = List(Article(NPHYS,nphys1906))

Page 52: (How) can we benefit from adopting scala?

XML literals and XPath-like processing

// given

val xml = <article id="1">

<doi>10.1038/nature01234</doi>

<title>A Title</title>

</article>

// then

assertThat(xml \ "@id" text, is("1"))

assertThat(xml \"doi" text, is("10.1038/nature01234"))

Page 53: (How) can we benefit from adopting scala?

Evaluating Scala code in XML literal

// given

val tstamp = System.currentTimeMillis

val xml = <timestamp>{tstamp}</timestamp>

// then

xml = <timestamp>1295726256063</timestamp>

Page 54: (How) can we benefit from adopting scala?

Loading XML// given

val xml = XML.loadString("<code>ABC</code>")

// then

assertThat(xml, is(<code>ABC</code>))

Page 55: (How) can we benefit from adopting scala?

Pattern matching on XMLval xml = <info>

<message>a message</message>

</info>

val result = xml match {

case <info>{_*}</info> => logInfo(xml)

case <error>{_*}</error> => logError(xml)

}

Page 56: (How) can we benefit from adopting scala?

Concurrency – Actor model

• Asynchronous message passing between actors

• Messages are immutable• Synchronized mailbox• Mailbox is read with pattern matching• No shared state + No locks = Safe concurrency• Actors are lightweight → millions of them on

regular box

Page 57: (How) can we benefit from adopting scala?

Type parameterizationclass A

class B extends A

class C extends B

def upperBound[T <: B](o: T) {}

upperBound(new A)

upperBound(new B)

upperBound(new C)

Page 58: (How) can we benefit from adopting scala?

Type parameterizationdef getSize[T <: { def size: Int }](o: T): Int = {

o.size

}

getSize(List(1, 2, 3))

getSize(new StringBuilder("abc"))

getSize("abc") // String has length() not size()

Page 59: (How) can we benefit from adopting scala?

Automatic Resource Managementuse of type parameterization and closure

def using[T <: {def close()}](resource: T)(block: T => Unit) = {

try {

block(resource)

} finally {

if (resource != null) {

try resource.close

catch {

case e: Exception =>

}

}

}

}

Page 60: (How) can we benefit from adopting scala?

Automatic Resource Managementusing(stream) { // where stream is InputStream

res => { val data = res.read }

}

using(resultSet) { // where resultSet is ResultSet

res => {

val data = if (res.next) res.getString("column") else ""

}

}

Page 61: (How) can we benefit from adopting scala?

ScalaTest BDD testing DSLclass StackSpec extends Spec with ShouldMatchers {

describe("A Stack") {

describe("(when empty)") {

val stack = new Stack[Int]

it("should be empty") {

stack should be ('empty)

}

it("should complain when popped") {

evaluating { stack.pop() } should produce [NoSuchElementException]

}

}

}

}

Page 62: (How) can we benefit from adopting scala?

Tooling

• Plugins for Eclipse, NetBeans and IDEA• Support for (some) refactorings, debugging,

code completion, hints, syntax highlighting, navigation

• maven support (also mix Java/Scala projects)• sbt – simple build tool

Page 63: (How) can we benefit from adopting scala?

Benefits

• Productivity• Functional aspects• XML• DSL• Concurrency

Page 64: (How) can we benefit from adopting scala?

Quirks (functions)Way functions are declared determines how they can be used

def foo = 1

def bar() = 2

foo

foo()

bar

bar()

Page 65: (How) can we benefit from adopting scala?

Warning!

There is a danger that once you start programming in Scala you may not want to

program in Java anymore!

Page 66: (How) can we benefit from adopting scala?

ResourcesScala - http://www.scala-lang.org/

A Tour of Scala - http://www.scala-lang.org/node/104

Scala API - http://www.scala-lang.org/api/current/index.html

New features of Scala 2.8 - http://escalatesoft.com/screencasts

Scala for Java Refugeeshttp://www.codecommit.com/blog/scala/roundup-scala-for-java-refugees

AlBlue’s Blog - http://alblue.bandlem.com/search/label/scala

Scala Style Guide (good to learn about some Scala quirks) - http://davetron5000.github.com/scala-style/

Scaling Web Apps with Akka - http://maciejmatyjas.com/2010/07/scaling-web-apps-with-akka/

Page 67: (How) can we benefit from adopting scala?

ResourcesProgramming in Scala - http://www.artima.com/shop/programming_in_scala

Programming Scala - http://programming-scala.labs.oreilly.com/

Seven Languages in Seven Weeks (chapter, comparison with Java and Ruby)http://pragprog.com/titles/btlang/seven-languages-in-seven-weeks

Programming Scala - http://pragprog.com/titles/vsscala/programming-scala

Page 68: (How) can we benefit from adopting scala?

Scala in London

London Scala User Group http://www.meetup.com/london-scala/

regular meetups – recorded and available athttp://skillsmatter.com/go/scala

LSUG Scala Dojo

Page 69: (How) can we benefit from adopting scala?

Thanks!

http://tomaszwrobel.com@twr_wrtp