If I were to pick a language to use on the JVM
today other than Java, it would be Scala.
– James Gosling, creator of Java
http://www.adam-bien.com/roller/abien/entry/java_net_javaone_which_programming
Scala, it must be stated, is the current heir apparent to the
Java throne. No other language on the JVM seems as
capable of being a "replacement for Java" as Scala, and
the momentum behind Scala is now unquestionable.
– Charlies Nutter, JRuby lead
http://blog.headius.com/2009/04/future-part-one.html
My tip though for the long term replacement of javac is Scala.
I'm very impressed with it! I can honestly say if someone had
shown me the Programming in Scala book […] back in 2003
I'd probably have never created Groovy.
– James Strachan, creator of Groovy
http://macstrac.blogspot.com/2009/04/scala-as-long-term-replacement-for.html
Agenda
● Background and motivation
● Intro to Scala
● Basic syntax
● Pattern matching
● Functions
● Classes and traits
● <break />
● Practical Scala
About us
● Alf Kristian Støyle and Fredrik Vraalsen
● Java developers with 6 and 9 years experience
● Scala enthusiasts since 2008
● Developed SubmitIT for JavaZone
● Alf worked on Scala projects for
Kommuneforlaget
● Held 4 Scala training courses for 60+
participants
public class Person {
private int age;
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
class Person(var age: Int, var name: String)
List<Person> persons = ...
List<Person> adults = new LinkedList<Person>();
List<Person> kids = new LinkedList<Person>();
for (Person person : persons) {
if (person.getAge() < 18) {
kids.add(person);
} else {
adults.add(person);
}
}
val persons: List[Person] = ...
val (kids, adults) = persons.partition(_.age < 18)
using(new BufferedReader(new FileReader("f.txt"))) {
reader => println(reader.readLine())
}
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("f.txt"));
System.out.println(reader.readLine());
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
// Exception on close, ignore
}
}
}
Scala
● Object oriented and functional
● Statically typed
● Java compatible
● Compiles to Java bytecode
● Existing libraries/frameworks
● Better Java
http://4.bp.blogspot.com/_RshsKGzNxWA/TB9QhCXK0fI/AAAAAAAAAEc/MFwujJaIRmw/s1600/BlueRedPill.jpg
Variables
var i: Int = 42
Variables
var i = 42
i = 3
i = "Hello world!" // compile error
Values
val i = 42
i = 3 // compile error
Methods
def sum(a: Int, b: Int): Int = {
return a + b
}
Methods
def sum(a: Int, b: Int): Int = {
a + b
}
Methods
def sum(a: Int, b: Int) = {
a + b
}
Methods
def sum(a: Int, b: Int) = a + b
Methods
"apple".charAt(0)
"apple" charAt 0
1.0.+(2.0)
1.0 + 2.0
Collections
val list = List("apple", "orange", "banana")
val map = Map(1 -> "one", 2 -> "two")
val array = Array(1, 2, 3, 4, 5)
list(1) // orange
map(2) // two
array(3) // 4
myObject match {
case 1 => println("First")
case 2 => println("Second")
case _ => println("Unknown")
}
Pattern matching
myObject match {
case i: Int => println("Found number " + i)
case s: String => println("Found text " + s)
case _ => println("Unknown")
}
Pattern matching
val email = """(.+)@(.+)""".r
"scala@java.no" match {
case email(name, domain) =>
println("User " + name + " at " + domain)
case x => println(x + " is not an email")
}
Pattern matching
Functions
Functions
Predicate<Integer> even = new Predicate<Integer>() {
@Override
public boolean apply(Integer i) {
return i % 2 == 0;
}
};
List<Integer> numbers = … // 1, 2, 3, 4
Iterable<Integer> evenNums =
Iterables.filter(numbers, even);
=> [2, 4]
Google collections:
Functions
val even = (i: Int) => i % 2 == 0
val numbers = List(1, 2, 3, 4)
val evenNums = numbers.filter(even)
=> List(2, 4)
Scala collections:
Functions
val numbers = List(1, 2, 3, 4)
val evenNums = numbers.filter((i: Int) => i % 2 == 0)
=> List(2, 4)
Scala collections:
Functions
val numbers = List(1, 2, 3, 4)
val evenNums = numbers.filter(i => i % 2 == 0)
=> List(2, 4)
Scala collections:
Functions
val numbers = List(1, 2, 3, 4)
val evenNums = numbers.filter(_ % 2 == 0)
=> List(2, 4)
Scala collections:
Functions
Predicate<Integer> even = new Predicate<Integer>() {
@Override
public boolean apply(Integer i) {
return i % 2 == 0;
}
};
val numbers = List(1, 2, 3, 4)
val evenNums = numbers.filter(_ % 2 == 0)
=> List(2, 4)
Scala collections:
“Functional programming”
● First class functions
● Pattern matching
● …
Functional programming
● Mathematical functions have no side effects
● f(x) = 2x + 3
In practice
● Only immutable objects (and object graphs)
● All field must be immutable
● No side-effects from method calls
● All methods must return something
Immutable datastrukturer
for (Iterator i = persons.iterator(); i.hasNext();) {
Person person = (Person) i.next();
if (person.getAge() < 18) {
i.remove();
}
}
val adults = persons.filter(_.age >= 18)
Strive to be pure
● Concurrency
● Easier to avoid errors
● Easier to test
Control structures return values
val numbers = for (i <- 1 to 10) yield i
val res1 = if (cond) x else y
val res2 = try { x } catch { … y } finally { … }
Classes and constructors
class Person(val name: String, val age: Int)
Classes and constructors
class Person(val name: String, val age: Int) {
def this(name: String) = this(name, 42)
override def toString = "My age is " + age
}
Traits (= Interface + Mixin)
● “Multiple inheritance done right”
● Implement methods
● Initialize fields
scala.Ordered trait
trait Ordered[A] {
def compare(that: A): Int
def < (that: A) = this.compare(that) < 0
def > (that: A) = this.compare(that) > 0
def <= (that: A) = this.compare(that) <= 0
def >= (that: A) = this.compare(that) >= 0
}
The Ordered trait
class Person(val age: Int) extends Ordered[Person] {
def compare(other: Person) = this.age - other.age
}
val person1 = new Person(21)
val person2 = new Person(31)
person1.<(person2) // true
person1 <= person2 // true
person1 >= person2 // false
Just scratching the surface...
● Tuples
● Singleton objects
● Closures
● For-comprehensions
● Implicit conversions
● Actors
● Native XML data types
● Parsers
Q & A
val xml = <break time="30" />
Practical Scala
● The downside
● Tools
● ScalaTest
● Java interoperability
● Learning curve
● Your choice
● Implicit conversions
● Higher order functions
IDE support
● Netbeans - very good, but inferior in other
areas
● IntelliJ IDEA - very good, but slow compilation
● Eclipse - getting better, very fast when working
Backward compatibility
● Binary compatibility broken several times
● Think twice before using a library
● 2.7.3 – 2.7.4
● 2.8.0 <-> 2.8.1.RC4
Tools demo
● REPL - Read eval print loop
● Maven
● SBT - Simple Build Tool
● IntelliJ IDEA
ScalaTest demo
● DSL for testing
● Powerful assertions
● Different test styles
● JUnit
● Functional tests
● BDD test
The feel of Scala
http://parleys.com/#id=10&st=5&sl=1
Java interoperability demo
● Scala using Java
● Java using Scala
● Mixed projects?
Learning curve
● Syntax small smack in the face
● Easy to write Java-ish Scala
● The language scales with your understanding
● Gradually migrate to more functional style
What would you like to hear?
● Implicit conversion
● Why does "gnirtS.gnal.avaj".reverse work?
● Higher order functions
● How does the using/resource handling example work?
Higher order functions
Higher order functions
● Functions which take functions as parameters
and/or return functions
Higher order functions
First class functions:
val even: (Int => Boolean) = (i: Int) => i % 2 == 0
Higher order function:
def test(numbers: List[Int], f: Int => Boolean) = ...
Use:
test(List(1, 2, 3), (i: Int) => i % 2 == 0)
test(List(1, 2, 3), _ % 2 == 0)
Higher order functions
def test(numbers: List[Int], f: Int => Boolean): List[Boolean] =
numbers.map(tall => f(tall))
Higher order functions
def test(numbers: List[Int], f: Int => Boolean): List[Boolean] =
numbers.map(tall => f(tall))
Use:
test(List(1, 2, 3), _ % 2 == 0) // List(false, true, false)
call-by-value vs. call-by-name
● by-value: expressions are evaluated before
being passed to the function
● by-name: expressions evaluated inside function
● nice when computationally expensive
● possible to create nice APIs
call-by-value vs. call-by-name
Example: Logging
def thisTakesTime = {
println(“Slow computation”)
“result”
}
call-by-value
def debug(s: String) {
println(“debug”)
if (logLevel <= DEBUG) println(s)
}
logger.debug(thisTakesTime())
// Slow computation
// debug
// result
call-by-name
def debug(s: => String) {
println(“debug”)
if (logLevel <= DEBUG) println(s)
}
logger.debug(thisTakesTime())
// debug
// Slow computation
// result
using(new BufferedReader(new FileReader("f.txt"))) {
reader => println(reader.readLine())
}
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("f.txt"));
System.out.println(reader.readLine());
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
// Exception on close, ignore
}
}
}
def using[T <: { def close() }, A]
(closeable: T)
(f: T => A) = {
try {
f(closeable)
} finally {
if (closeable != null) {
try {
closeable.close()
}
catch {
case e: Exception => // Ignore
}
}
}
}
using(new BufferedReader(new FileReader("f.txt"))) {
reader => println(reader.readLine())
}
Implicit conversions
String s = "!em esreveR";
System.out.println(s.reverse());
Magic?
val s: java.lang.String = "!em esreveR"
println(s.reverse)
=> Reverse me!
Magic?
val s: java.lang.String = "!em esreveR"
println(s.reverse)
println(stringWrapper(s).reverse)
=> Reverse me!
String s = "!em esreveR";
System.out.println(s.reverse());
Magic?
val s: java.lang.String = "!em esreveR"
println(s.reverse)
println(augmentString(s).reverse)
println(new StringOps(s).reverse)
=> Reverse me!
String s = "!em esreveR";
System.out.println(s.reverse());
implicit
implicit def augmentString(x: String) =
new StringOps(x)
StringOps
def toArray : Array[Char]
def toBoolean : Boolean
def toByte : Byte
def toDouble : Double
def toFloat : Float
def toInt : Int
def toLong : Long
def toShort : Short
def r : Regex
def lines : Iterator[java.lang.String]
def * (n : Int) : java.lang.String
...
scala.Predef
● A set of implicits
● byteWrapper(x: Byte)
● shortWrapper(x: Short)
● intWrapper(x: Int)
● charWrapper(c: Char)
● longWrapper(x: Long)
● floatWrapper(x: Float)
● doubleWrapper(x: Double)
● booleanWrapper(x: Boolean)
● stringWrapper(x: String)
● stringBuilderWrapper(x :
StringBuilder)
● ...
Map and ArrowAssoc
val myMap: Map[Int, String] =
Map(1 -> "one", 2 -> "two")
Map and ArrowAssoc
val myMap: Map[Int, String] =
Map(1 -> "one", 2 -> "two")
Map.apply((1, "one"), (2, "two"))
Map and ArrowAssoc
val myMap: Map[Int, String] =
Map(1 -> "one", 2 -> "two")
Map((1, "one"), (2, "two"))
Map and ArrowAssoc
val myMap: Map[Int, String] =
Map(1 -> "one", 2 -> "two")
Map((1, "one"), (2, "two"))
val tuple: Tuple2[Int, String] = (1, "one")
Map and ArrowAssoc
val myMap: Map[Int, String] =
Map(1 -> "one", 2 -> "two")
Map(any2ArrowAssoc(1) -> "one",
any2ArrowAssoc(2) -> "two")
Map((1, "one"), (2, "two"))
scala.Predef.ArrowAssoc
implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A] =
new ArrowAssoc(x)
class ArrowAssoc[A](x: A) {
def -> [B](y: B): Tuple2[A, B] = (x, y)
}
val myMap = Map(1 -> "one", 2 -> "two")
Implicit rules!
● Marking Rule: Only definitions marked implicit are available.
● Scope Rule: An inserted implicit conversion must be in scope as a
single identifier, or be associated with the source or target type of the
conversion.
● Non-Ambiguity Rule: An implicit conversion is only inserted if there is
no other possible conversion to insert.
● One-at-a-time Rule: Only one implicit is tried.
● Explicits-First Rule: Whenever code type checks as it is written, no
implicits are attempted.
Q & A
Resources
● scala@java.no
(http://lister.java.no/mailman/listinfo/scala)
● http://scala.java.no
● http://www.slideshare.net/stoyle/scala-ntnu
● http://github.com/javaBin/scala-training-slides
● fvr@knowit.no, aks@knowit.no

Scala ntnu

  • 1.
    If I wereto pick a language to use on the JVM today other than Java, it would be Scala. – James Gosling, creator of Java http://www.adam-bien.com/roller/abien/entry/java_net_javaone_which_programming Scala, it must be stated, is the current heir apparent to the Java throne. No other language on the JVM seems as capable of being a "replacement for Java" as Scala, and the momentum behind Scala is now unquestionable. – Charlies Nutter, JRuby lead http://blog.headius.com/2009/04/future-part-one.html My tip though for the long term replacement of javac is Scala. I'm very impressed with it! I can honestly say if someone had shown me the Programming in Scala book […] back in 2003 I'd probably have never created Groovy. – James Strachan, creator of Groovy http://macstrac.blogspot.com/2009/04/scala-as-long-term-replacement-for.html
  • 2.
    Agenda ● Background andmotivation ● Intro to Scala ● Basic syntax ● Pattern matching ● Functions ● Classes and traits ● <break /> ● Practical Scala
  • 3.
    About us ● AlfKristian Støyle and Fredrik Vraalsen ● Java developers with 6 and 9 years experience ● Scala enthusiasts since 2008 ● Developed SubmitIT for JavaZone ● Alf worked on Scala projects for Kommuneforlaget ● Held 4 Scala training courses for 60+ participants
  • 5.
    public class Person{ private int age; private String name; public Person(int age, String name) { this.age = age; this.name = name; } public int getAge() { return this.age; } public void setAge(int age) { this.age = age; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } } class Person(var age: Int, var name: String)
  • 6.
    List<Person> persons =... List<Person> adults = new LinkedList<Person>(); List<Person> kids = new LinkedList<Person>(); for (Person person : persons) { if (person.getAge() < 18) { kids.add(person); } else { adults.add(person); } } val persons: List[Person] = ... val (kids, adults) = persons.partition(_.age < 18)
  • 7.
    using(new BufferedReader(new FileReader("f.txt"))){ reader => println(reader.readLine()) } BufferedReader reader = null; try { reader = new BufferedReader(new FileReader("f.txt")); System.out.println(reader.readLine()); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { // Exception on close, ignore } } }
  • 8.
    Scala ● Object orientedand functional ● Statically typed ● Java compatible ● Compiles to Java bytecode ● Existing libraries/frameworks ● Better Java
  • 9.
  • 10.
  • 11.
    Variables var i =42 i = 3 i = "Hello world!" // compile error
  • 12.
    Values val i =42 i = 3 // compile error
  • 13.
    Methods def sum(a: Int,b: Int): Int = { return a + b }
  • 14.
    Methods def sum(a: Int,b: Int): Int = { a + b }
  • 15.
    Methods def sum(a: Int,b: Int) = { a + b }
  • 16.
    Methods def sum(a: Int,b: Int) = a + b
  • 17.
  • 18.
    Collections val list =List("apple", "orange", "banana") val map = Map(1 -> "one", 2 -> "two") val array = Array(1, 2, 3, 4, 5) list(1) // orange map(2) // two array(3) // 4
  • 19.
    myObject match { case1 => println("First") case 2 => println("Second") case _ => println("Unknown") } Pattern matching
  • 20.
    myObject match { casei: Int => println("Found number " + i) case s: String => println("Found text " + s) case _ => println("Unknown") } Pattern matching
  • 21.
    val email ="""(.+)@(.+)""".r "scala@java.no" match { case email(name, domain) => println("User " + name + " at " + domain) case x => println(x + " is not an email") } Pattern matching
  • 22.
  • 23.
    Functions Predicate<Integer> even =new Predicate<Integer>() { @Override public boolean apply(Integer i) { return i % 2 == 0; } }; List<Integer> numbers = … // 1, 2, 3, 4 Iterable<Integer> evenNums = Iterables.filter(numbers, even); => [2, 4] Google collections:
  • 24.
    Functions val even =(i: Int) => i % 2 == 0 val numbers = List(1, 2, 3, 4) val evenNums = numbers.filter(even) => List(2, 4) Scala collections:
  • 25.
    Functions val numbers =List(1, 2, 3, 4) val evenNums = numbers.filter((i: Int) => i % 2 == 0) => List(2, 4) Scala collections:
  • 26.
    Functions val numbers =List(1, 2, 3, 4) val evenNums = numbers.filter(i => i % 2 == 0) => List(2, 4) Scala collections:
  • 27.
    Functions val numbers =List(1, 2, 3, 4) val evenNums = numbers.filter(_ % 2 == 0) => List(2, 4) Scala collections:
  • 28.
    Functions Predicate<Integer> even =new Predicate<Integer>() { @Override public boolean apply(Integer i) { return i % 2 == 0; } }; val numbers = List(1, 2, 3, 4) val evenNums = numbers.filter(_ % 2 == 0) => List(2, 4) Scala collections:
  • 29.
    “Functional programming” ● Firstclass functions ● Pattern matching ● …
  • 30.
    Functional programming ● Mathematicalfunctions have no side effects ● f(x) = 2x + 3
  • 31.
    In practice ● Onlyimmutable objects (and object graphs) ● All field must be immutable ● No side-effects from method calls ● All methods must return something
  • 32.
    Immutable datastrukturer for (Iteratori = persons.iterator(); i.hasNext();) { Person person = (Person) i.next(); if (person.getAge() < 18) { i.remove(); } } val adults = persons.filter(_.age >= 18)
  • 33.
    Strive to bepure ● Concurrency ● Easier to avoid errors ● Easier to test
  • 34.
    Control structures returnvalues val numbers = for (i <- 1 to 10) yield i val res1 = if (cond) x else y val res2 = try { x } catch { … y } finally { … }
  • 35.
    Classes and constructors classPerson(val name: String, val age: Int)
  • 36.
    Classes and constructors classPerson(val name: String, val age: Int) { def this(name: String) = this(name, 42) override def toString = "My age is " + age }
  • 37.
    Traits (= Interface+ Mixin) ● “Multiple inheritance done right” ● Implement methods ● Initialize fields
  • 38.
    scala.Ordered trait trait Ordered[A]{ def compare(that: A): Int def < (that: A) = this.compare(that) < 0 def > (that: A) = this.compare(that) > 0 def <= (that: A) = this.compare(that) <= 0 def >= (that: A) = this.compare(that) >= 0 }
  • 39.
    The Ordered trait classPerson(val age: Int) extends Ordered[Person] { def compare(other: Person) = this.age - other.age } val person1 = new Person(21) val person2 = new Person(31) person1.<(person2) // true person1 <= person2 // true person1 >= person2 // false
  • 40.
    Just scratching thesurface... ● Tuples ● Singleton objects ● Closures ● For-comprehensions ● Implicit conversions ● Actors ● Native XML data types ● Parsers
  • 41.
  • 42.
    val xml =<break time="30" />
  • 43.
    Practical Scala ● Thedownside ● Tools ● ScalaTest ● Java interoperability ● Learning curve ● Your choice ● Implicit conversions ● Higher order functions
  • 44.
    IDE support ● Netbeans- very good, but inferior in other areas ● IntelliJ IDEA - very good, but slow compilation ● Eclipse - getting better, very fast when working
  • 45.
    Backward compatibility ● Binarycompatibility broken several times ● Think twice before using a library ● 2.7.3 – 2.7.4 ● 2.8.0 <-> 2.8.1.RC4
  • 46.
    Tools demo ● REPL- Read eval print loop ● Maven ● SBT - Simple Build Tool ● IntelliJ IDEA
  • 47.
    ScalaTest demo ● DSLfor testing ● Powerful assertions ● Different test styles ● JUnit ● Functional tests ● BDD test
  • 48.
    The feel ofScala http://parleys.com/#id=10&st=5&sl=1
  • 49.
    Java interoperability demo ●Scala using Java ● Java using Scala ● Mixed projects?
  • 50.
    Learning curve ● Syntaxsmall smack in the face ● Easy to write Java-ish Scala ● The language scales with your understanding ● Gradually migrate to more functional style
  • 51.
    What would youlike to hear? ● Implicit conversion ● Why does "gnirtS.gnal.avaj".reverse work? ● Higher order functions ● How does the using/resource handling example work?
  • 52.
  • 53.
    Higher order functions ●Functions which take functions as parameters and/or return functions
  • 54.
    Higher order functions Firstclass functions: val even: (Int => Boolean) = (i: Int) => i % 2 == 0 Higher order function: def test(numbers: List[Int], f: Int => Boolean) = ... Use: test(List(1, 2, 3), (i: Int) => i % 2 == 0) test(List(1, 2, 3), _ % 2 == 0)
  • 55.
    Higher order functions deftest(numbers: List[Int], f: Int => Boolean): List[Boolean] = numbers.map(tall => f(tall))
  • 56.
    Higher order functions deftest(numbers: List[Int], f: Int => Boolean): List[Boolean] = numbers.map(tall => f(tall)) Use: test(List(1, 2, 3), _ % 2 == 0) // List(false, true, false)
  • 57.
    call-by-value vs. call-by-name ●by-value: expressions are evaluated before being passed to the function ● by-name: expressions evaluated inside function ● nice when computationally expensive ● possible to create nice APIs
  • 58.
    call-by-value vs. call-by-name Example:Logging def thisTakesTime = { println(“Slow computation”) “result” }
  • 59.
    call-by-value def debug(s: String){ println(“debug”) if (logLevel <= DEBUG) println(s) } logger.debug(thisTakesTime()) // Slow computation // debug // result
  • 60.
    call-by-name def debug(s: =>String) { println(“debug”) if (logLevel <= DEBUG) println(s) } logger.debug(thisTakesTime()) // debug // Slow computation // result
  • 61.
    using(new BufferedReader(new FileReader("f.txt"))){ reader => println(reader.readLine()) } BufferedReader reader = null; try { reader = new BufferedReader(new FileReader("f.txt")); System.out.println(reader.readLine()); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { // Exception on close, ignore } } }
  • 62.
    def using[T <:{ def close() }, A] (closeable: T) (f: T => A) = { try { f(closeable) } finally { if (closeable != null) { try { closeable.close() } catch { case e: Exception => // Ignore } } } } using(new BufferedReader(new FileReader("f.txt"))) { reader => println(reader.readLine()) }
  • 63.
  • 64.
    String s ="!em esreveR"; System.out.println(s.reverse()); Magic? val s: java.lang.String = "!em esreveR" println(s.reverse) => Reverse me!
  • 65.
    Magic? val s: java.lang.String= "!em esreveR" println(s.reverse) println(stringWrapper(s).reverse) => Reverse me! String s = "!em esreveR"; System.out.println(s.reverse());
  • 66.
    Magic? val s: java.lang.String= "!em esreveR" println(s.reverse) println(augmentString(s).reverse) println(new StringOps(s).reverse) => Reverse me! String s = "!em esreveR"; System.out.println(s.reverse());
  • 67.
    implicit implicit def augmentString(x:String) = new StringOps(x)
  • 68.
    StringOps def toArray :Array[Char] def toBoolean : Boolean def toByte : Byte def toDouble : Double def toFloat : Float def toInt : Int def toLong : Long def toShort : Short def r : Regex def lines : Iterator[java.lang.String] def * (n : Int) : java.lang.String ...
  • 69.
    scala.Predef ● A setof implicits ● byteWrapper(x: Byte) ● shortWrapper(x: Short) ● intWrapper(x: Int) ● charWrapper(c: Char) ● longWrapper(x: Long) ● floatWrapper(x: Float) ● doubleWrapper(x: Double) ● booleanWrapper(x: Boolean) ● stringWrapper(x: String) ● stringBuilderWrapper(x : StringBuilder) ● ...
  • 70.
    Map and ArrowAssoc valmyMap: Map[Int, String] = Map(1 -> "one", 2 -> "two")
  • 71.
    Map and ArrowAssoc valmyMap: Map[Int, String] = Map(1 -> "one", 2 -> "two") Map.apply((1, "one"), (2, "two"))
  • 72.
    Map and ArrowAssoc valmyMap: Map[Int, String] = Map(1 -> "one", 2 -> "two") Map((1, "one"), (2, "two"))
  • 73.
    Map and ArrowAssoc valmyMap: Map[Int, String] = Map(1 -> "one", 2 -> "two") Map((1, "one"), (2, "two")) val tuple: Tuple2[Int, String] = (1, "one")
  • 74.
    Map and ArrowAssoc valmyMap: Map[Int, String] = Map(1 -> "one", 2 -> "two") Map(any2ArrowAssoc(1) -> "one", any2ArrowAssoc(2) -> "two") Map((1, "one"), (2, "two"))
  • 75.
    scala.Predef.ArrowAssoc implicit def any2ArrowAssoc[A](x:A): ArrowAssoc[A] = new ArrowAssoc(x) class ArrowAssoc[A](x: A) { def -> [B](y: B): Tuple2[A, B] = (x, y) } val myMap = Map(1 -> "one", 2 -> "two")
  • 76.
    Implicit rules! ● MarkingRule: Only definitions marked implicit are available. ● Scope Rule: An inserted implicit conversion must be in scope as a single identifier, or be associated with the source or target type of the conversion. ● Non-Ambiguity Rule: An implicit conversion is only inserted if there is no other possible conversion to insert. ● One-at-a-time Rule: Only one implicit is tried. ● Explicits-First Rule: Whenever code type checks as it is written, no implicits are attempted.
  • 77.
  • 78.
    Resources ● scala@java.no (http://lister.java.no/mailman/listinfo/scala) ● http://scala.java.no ●http://www.slideshare.net/stoyle/scala-ntnu ● http://github.com/javaBin/scala-training-slides ● fvr@knowit.no, aks@knowit.no

Editor's Notes

  • #54 Denne siden skal vel bort?
  • #60 Bruke logging eksempelet
  • #61 Logging?