(How) can we benefit from adopting scala?
Upcoming SlideShare
Loading in...5
×
 

(How) can we benefit from adopting scala?

on

  • 1,942 views

 

Statistics

Views

Total Views
1,942
Views on SlideShare
1,839
Embed Views
103

Actions

Likes
2
Downloads
21
Comments
0

4 Embeds 103

http://tomaszwrobel.com 80
http://www.linkedin.com 16
https://www.linkedin.com 6
http://twr-mbp.lan 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • In static typing all expressions have their types determined prior to the program being run (typically at compile-time). Dynamic typing determines the type-safety of operations at runtime - types are associated with runtime values rather than textual expressions. Strong typing = type safe Weak typing allows a value of one type to be treated as another. Think of if(1) {} Static/Dynamic typing is about when type information is acquired (Either at compile- or at runtime) Strong/Weak typing is about how strictly types are distinguished (e.g. whether the language tries to do implicit conversion from strings to numbers). Strong typing means the language detects when two types are compatible – it can throw an error or coerce the types if they are not. Static typing – compilers know more about your code, greater tool support.
  • It's true that tools now can generate most of the boilerplate code for us. Unfortunately they do not read it yet.
  • Functional programs are made up of functions. A function always returns a value. A function, given the same inputs, will return the same values. Functional programs avoid changing state or mutating data. Functional programming concepts are important when dealing with concurrent applications. Functional programming is a declarative style in which you say what to do instead of how something should be done. Java is imperative.
  • Few words on class, variables and methods
  • Scala forces you to explicitly make a decision about whether a variable is mutable.
  • Compiler sees Int But Int does not have days function It then searches for a implicit conversion from Int to a type that support days It finds method converting Int to DateHelper Compiler invokes days on DateHelper
  • decorate objects with capabilities add behaviours to the class hierarchy
  • Helper functions do not pollute namespace
  • Closure = function literal that binds to, or close over, variables outside of their local scope and parameter list. A closure is simply a more convenient way to give a function access to local state.
  • No new keyword. But constructor is an option too. This is used in pattern matching.
  • Pattern matching is used to conditionally execute code based on some piece of data.
  • Scala does not require catching checked exceptions
  • Scala comes with their own collections. You can still use java collections however. By default you work with immutable collections. There are mutable implementations as well.
  • Except functions you would normally expect defined on a collection: length, reverse, contains, slice, etc.
  • an Actor is an object that receives messages and takes action on those messages
  • http://www.scalatest.org/
  • IDEA: rename – SHIFT + F6 format – ALT + CMD + L refactor new FileReader – gives you a hint Alt+Enter
  • Have a look at Scala API - dynamic

(How) can we benefit from adopting scala? (How) can we benefit from adopting scala? Presentation Transcript

  • (How) Can we benefit from adopting Scala ? Tomasz Wróbel, 2011-01-24
  • in other words what Scala has to offer
  • 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
  • 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
  • Support for both functional and object-oriented programming paradigms
    • Code blocks (anonymous functions)
    • Higher-order functions (ones that produce or consume functions)
    • Closures
    • Sophisticated collection library
  • REPL
    • R ead- E valuate- P rint L oop
    • scala> val s = "Hello!"
    • s: java.lang.String = Hello!
    • scala> println(s)
    • Hello!
  • 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)
  • 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;
    • }
  • 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(&quot;abc&quot;)
  • Type inference
    • val 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
  • operators = functions
    • 1 + 2 is actually (1).+(2)
    • operators overloading
    • possibility to define new data types
  • Euro
    • case 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)))
  • Ranges
    • val 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))
  • Tuples
    • are typed
    • scala> val tuple = (&quot;CODE&quot;, 31)
    • tuple: (java.lang.String, Int) = (CODE,31)
  • 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(&quot;abc&quot;)
    • result: (String, Int) = (ABC,3)
  • Controlling executions
    • for (i <- 0 to 9) {
    • print(i)
    • }
    • var i = 0
    • while (i < 10) {
    • print(i)
    • i += 1
    • }
    • for (i <- 0 to 9) {
    • if (i % 2 == 0) println(&quot;even: &quot; + i) else println(&quot;odd: &quot; + i)
    • }
  • Raw strings
    • // given
    • val s = &quot;&quot;&quot;|first line
    • |second &quot;B&quot; line
    • |third line&quot;&quot;&quot;.stripMargin
    • // then
    • assertThat(s, is(&quot; first linensecond &quot;B&quot; linenthird line&quot; ))
  • Raw strings
    • assertThat(&quot;1234&quot;.matches( &quot;&quot;&quot;d*&quot;&quot;&quot; ), is(true))
    • assertThat(&quot;12ab&quot;.matches( &quot;&quot;&quot;d*&quot;&quot;&quot; ), is(false))
    • new File( &quot;&quot;&quot;c:somepathtofile.txt&quot;&quot;&quot; ).exists
  • Making assertions
    • @Test(expected = classOf[ IllegalArgumentException ])
    • def convenientAssertions {
    • val i = -1
    • require(i > 0)
    • }
  • Objects equality
    • == is Java's equals()
    • eq() is Java's ==
  • Imports
    • import 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}
  • 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
  • There is always an Option i.e. null alternative
    • scala> def map = Map(&quot;PL&quot; -> &quot;Poland&quot;)
    • scala> val country: Option[String] = map.get(&quot;PL&quot;)
    • country: Option[String] = Some(Poland)
    • scala> val res = country. get
    • res: String = Poland
    • scala> val res = country. getOrElse(&quot;default&quot;)
    • res: String = Poland
    • scala> val country: Option[String] = map.get(&quot;UK&quot;)
    • country: Option[String] = None
    • scala> val res = country. getOrElse(&quot;default&quot;)
    • res: String = default
    • scala> val res = country. get
    • java.util. NoSuchElementException : None.get
  • Implicits
    • Allow to add functionality to existing classes
    • val 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
  • 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
  • class and object
    • class Article private (title: String)
    • object Article {
    • def newInstance(title: String) = new Article(title)
    • }
    • object App {
    • def main(args: Array[String]) {
    • val article = Article.newInstance(&quot;a Title&quot;)
    • }
    • }
  • Traits
    • trait SingleJournalRelease extends PressRelease {
    • override def validate = println(&quot;articles form the same journal&quot;)
    • }
    • trait IssueRelease extends PressRelease {
    • override def header = print(&quot;Issue Press Release containing &quot;)
    • }
    • trait AopRelease extends PressRelease {
    • override def header = print(&quot;AOP Press Release containing &quot;)
    • }
    • class AcademicJournalAopPressRelease extends AopRelease with SingleJournalRelease
    • class ResearchJournalIssuePressRelease extends IssueRelease with SingleJournalRelease
  • Anonymous functions
    • val list = List(1, 2, 3)
    • val odds = list.filter( (each: Int) => each % 2 != 0 )
    • assertThat(odds, is(List(1, 3)))
  • Functions
    • Functions can be assigned to variables and be passed as parameters
    • val complicatedProcessing = (s: String) => s.toUpperCase
    • assertThat( complicatedProcessing(&quot;abc&quot;) , is(&quot;ABC&quot;))
    • val list = List(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;)
    • val result = list.map( complicatedProcessing )
    • assertThat(result, is(List(&quot;A&quot;, &quot;B&quot;, &quot;C&quot;)))
  • Local functions
    • Functions can be nested
    • def outer {
    • def inner(s: String) = println(&quot;inner &quot; + s)
    • inner(&quot;outer&quot;)
    • }
  • Passing parameters to functions
    • scala> def fun (s: String) = println(s)
    • fun: (s: String)Unit
    • scala> fun (&quot;abc&quot;)
    • abc
    • scala> fun {&quot;abc&quot;}
    • abc
  • 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
  • Adding new control structures
    • for (i <- 0 to 9) {
    • print(i)
    • }
    • writeToFile (&quot;output.txt&quot;) {
    • writer => writer.println(&quot;abc&quot;)
    • }
    • def writeToFile(fileName: String)(block : PrintWriter => Unit) = {
    • val writer = new PrintWriter(new File(fileName))
    • try { block(writer) } finally writer.close()
    • }
  • Implementing unless
    • scala> def unless(cond: => Boolean)(body: => Unit): Unit =
    • | if (!cond) {
    • | body
    • | }
    • unless: (cond: => Boolean)(body: => Unit)Unit
    • scala> unless(1 > 2) {
    • | print(&quot;1 is not greater than 2&quot;)
    • | }
    • 1 is not greater than 2
  • Closures
    • // given
    • val base = 100
    • def closeAroundBase(i: Int) = {
    • i + base
    • }
    • // then
    • assertThat(closeAroundBase(10), is(110))
  • Why is closure useful?
    • val patternProvidedByUser = &quot;L.*&quot;
    • val data = List(&quot;London&quot;, &quot;Oxford&quot;, &quot;Leeds&quot;)
    • val result = data.filter(_.matches( patternProvidedByUser ))
    • result: List[java.lang.String] = List(London, Leeds)
  • Case classes
    • case class Article(var doi: String, var title: String)
    • // Provide convenient factory method
    • val article = Article (&quot;10.1038/nature01234&quot;, &quot;a Title&quot;)
    • // and implementations for
    • assertThat(&quot; toString &quot;, article. toString , is( &quot;Article(10.1038/nature01234,a Title)&quot; ))
    • assertThat(&quot; hashCode &quot;, article. hashCode , equalTo( equalArticle. hashCode ))
    • assertTrue(&quot; equals &quot;, article == equalArticle)
  • Pattern matching
    • match as switch on steroids
    • always results in a value
    • no “fall through”
    • MatchError thrown if no match
    • _ is default
  • Matching by constant
    • def fun(o: Any): Int = o match {
    • case &quot;abc&quot; => 1
    • case 1 => 2
    • case Nil => 0
    • }
  • 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(&quot;abc&quot;), is(3))
    • assertThat(size(List(1, 2)), is(2))
  • Matching by tuple
    • def fun(o: Any): Any = o match {
    • case (a: Int, b: Int) => a + b
    • }
  • Matching by constructor
    • case class Rectangle(a: Int, b: Int)
    • def identify(r: Rectangle): String = r match {
    • case Rectangle(2, 4) => &quot;2x4&quot;
    • case Rectangle(a, b) if a == b => &quot;Square&quot; // pattern guard
    • case Rectangle(a, b) => &quot;Rectangle &quot; + a + &quot;x&quot; + b
    • }
    • assertThat(identify(Rectangle(2, 4)), is(&quot;2x4&quot;))
    • assertThat(identify(Rectangle(1, 1)), is(&quot;Square&quot;))
    • assertThat(identify(Rectangle(1, 2)), is(&quot;Rectangle 1x2&quot;))
  • (optional) Exception handling
    • try {
    • val f = new FileInputStream(&quot;file.txt&quot;)
    • } catch {
    • case e: IOException => // handle the exception
    • }
    • but can be also just:
    • val f = new FileInputStream(&quot;file.txt&quot;)
  • Named and default parameters
    • case class Article(id: Int, doi: String, title: String)
    • def make(id: Int = 1 , doi: String = &quot;a Doi&quot; , title: String = &quot;a Title&quot; ) = {
    • Article(id, doi, title)
    • }
  • Named and default parameters Defaulting omitted parameter(s)
    • val article = make( 99, &quot;10.1038/nature01234&quot; )
    • assertThat(article.id, is(99))
    • assertThat(article.doi, is(&quot;10.1038/nature01234&quot;))
    • assertThat(article.title, is( &quot;a Title&quot; ))
  • Named and default parameters Setting parameter by name
    • val article = make(doi = &quot;10.1038/nature01234&quot; )
    • assertThat(article.id, is(1)) // default
    • assertThat(article.doi, is( &quot;10.1038/nature01234&quot; ))
    • assertThat(article.title, is(&quot;a Title&quot;)) // default
  • Collections Easy construction
    • val aList = List(1, 2, 3)
    • val aMap = Map(&quot;A&quot; -> 1, &quot;B&quot; -> 2, &quot;C&quot; -> 3)
    • val aSet = Set(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;b&quot;, &quot;a&quot;)
    • 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)
  • Collections Iterable - 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)
  • Collections
    • scala> val result = numbers . mkString(&quot;, &quot;)
    • result: String = 1, 2, 3, 4, 5
    • scala> val result = numbers. count(_ > 2)
    • result: Int = 3
    • scala> numbers. foreach(print _)
    • 12345
  • Collections Example for groupBy
    • scala> case class Article(journal: String, doi: String)
    • scala> val articles = List( Article(&quot;NATURE&quot;, &quot;nature09733&quot;), Article(&quot;NMAT&quot;, &quot;nmat2937&quot;), Article(&quot;NMAT&quot;, &quot;nmat1807&quot;), Article(&quot;NPHYS&quot;, &quot;nphys1906&quot;))
    • scala> val result = articles. groupBy(e => e.journal)
    • scala> val nmat = result(&quot;NMAT&quot;)
    • nmat: List[Article] = List(Article(NMAT,nmat2937), Article(NMAT,nmat1807))
    • scala> val nature = result(&quot;NATURE&quot;)
    • nature: List[Article] = List(Article(NATURE,nature09733))
    • scala> val nphys = result(&quot;NPHYS&quot;)
    • nphys: List[Article] = List(Article(NPHYS,nphys1906))
  • XML literals and XPath-like processing
    • // given
    • val xml = <article id=&quot; 1 &quot;>
    • <doi> 10.1038/nature01234 </doi>
    • <title>A Title</title>
    • </article>
    • // then
    • assertThat(xml &quot;@id&quot; text, is(&quot; 1 &quot;))
    • assertThat(xml &quot;doi&quot; text, is(&quot; 10.1038/nature01234 &quot;))
  • Evaluating Scala code in XML literal
    • // given
    • val tstamp = System.currentTimeMillis
    • val xml = <timestamp> {tstamp} </timestamp>
    • // then
    • xml = <timestamp> 1295726256063 </timestamp>
  • Loading XML
    • // given
    • val xml = XML. loadString (&quot;<code>ABC</code>&quot;)
    • // then
    • assertThat(xml, is( <code>ABC</code> ))
  • Pattern matching on XML
    • val xml = <info>
    • <message>a message</message>
    • </info>
    • val result = xml match {
    • case <info>{_*}</info> => logInfo(xml)
    • case <error>{_*}</error> => logError(xml)
    • }
  • 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
  • Type parameterization
    • class A
    • class B extends A
    • class C extends B
    • def upperBound[ T <: B ](o: T) {}
    • upperBound(new A)
    • upperBound(new B)
    • upperBound(new C)
  • Type parameterization
    • def getSize[ T <: { def size: Int } ](o: T): Int = {
    • o.size
    • }
    • getSize(List(1, 2, 3))
    • getSize(new StringBuilder(&quot;abc&quot;))
    • getSize(&quot;abc&quot;) // String has length() not size()
  • Automatic Resource Management use 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 =>
    • }
    • }
    • }
    • }
  • Automatic Resource Management
    • using( stream ) { // where stream is InputStream
    • res => { val data = res .read }
    • }
    • using( resultSet ) { // where resultSet is ResultSet
    • res => {
    • val data = if (res.next) res .getString(&quot;column&quot;) else &quot;&quot;
    • }
    • }
  • ScalaTest BDD testing DSL
    • class StackSpec extends Spec with ShouldMatchers {
    • describe(&quot;A Stack&quot;) {
    • describe(&quot;(when empty)&quot;) {
    • val stack = new Stack[Int]
    • it(&quot;should be empty&quot;) {
    • stack should be ('empty)
    • }
    • it(&quot;should complain when popped&quot;) {
    • evaluating { stack.pop() } should produce [NoSuchElementException]
    • }
    • }
    • }
    • }
  • 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
  • Benefits
    • Productivity
    • Functional aspects
    • XML
    • DSL
    • Concurrency
  • Quirks (functions)
    • Way functions are declared determines how they can be used
    • def foo = 1
    • def bar() = 2
    • foo
    • foo()
    • bar
    • bar()
  • Warning! There is a danger that once you start programming in Scala you may not want to program in Java anymore!
  • Resources
    • Scala - 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 Refugees http://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/
  • Resources
    • Programming 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
  • Scala in London
    • London Scala User Group http://www.meetup.com/london-scala/
    • regular meetups – recorded and available at http://skillsmatter.com/go/scala
    • LSUG Scala Dojo
  • Thanks! http://tomaszwrobel.com @twr_wrtp