3. 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
4. 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
5. 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
7. 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)
8. How difficult is it to switch?
Java → Scala
// class
public class A {} class A {}
// variable
private int i = 0; private var i: Int = 0;
// function
public String fun(String s) { def fun(s: String): String = {
return s; return s;
} }
9. 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")
10. 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
11. operators = functions
• 1 + 2 is actually (1).+(2)
• operators overloading
• possibility to define new data types
12. 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)))
13. 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))
15. 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)
16. Controlling executions
for (i <- 0 to 9) {
print(i)
}
for (i <- 0 to 9) {
if (i % 2 == 0) println("even: " + i) else
println("odd: " + i)
}
18. Raw strings
// given
val s = """|first line
|second "B" line
|third line""".stripMargin
// then
assertThat(s, is("first linensecond "B" linenthird
line"))
23. 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
24. There is always an Option
i.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
25. 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
26. 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
27. 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("a Title")
}
}
28. Traits
trait 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
29. Anonymous functions
val list = List(1, 2, 3)
val odds = list.filter((each: Int) => each % 2 != 0)
assertThat(odds, is(List(1, 3)))
30. 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")))
33. 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
34. Adding new control structures
writeToFile("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()
}
35. Implementing unless
scala> 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
36. Closures
// given
val base = 100
def closeAroundBase(i: Int) = {
i + base
}
// then
assertThat(closeAroundBase(10), is(110))
37. 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)
38. Case classes
case 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)
39. Pattern matching
• match as switch on steroids
• always results in a value
• no “fall through”
• MatchError thrown if no match
• _ is default
40. Matching by constant
def fun(o: Any): Int = o match {
case "abc" => 1
case 1 => 2
case Nil => 0
}
41. 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))
43. Matching by constructor
case 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"))
44. (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")
45. Named and default parameters
case 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)
}
46. Named and default parameters
Defaulting 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"))
47. Named and default parameters
Setting 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
48. Collections
Easy 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)
49. 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)
50. Collections
scala> 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
51. Collections
Example 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))
52. 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"))
53. Evaluating Scala code in XML literal
// given
val tstamp = System.currentTimeMillis
val xml = <timestamp>{tstamp}</timestamp>
// then
xml = <timestamp>1295726256063</timestamp>
54. Loading XML
// given
val xml = XML.loadString("<code>ABC</code>")
// then
assertThat(xml, is(<code>ABC</code>))
55. 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)
}
56. 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
57. 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)
58. Type parameterization
def 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()
59. 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 =>
}
}
}
}
60. 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("column")
else ""
}
}
61. ScalaTest BDD testing DSL
class 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]
}
}
}
}
62. 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
65. Warning!
There is a danger that once you start
programming in Scala you may not want to
program in Java anymore!
66. 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/
67. 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
68. 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
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