Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Meet scala

235 views

Published on

Concise presentation of scala features.

Published in: Software
  • Be the first to comment

  • Be the first to like this

Meet scala

  1. 1. Meet scala Wojciech Pituła For AMG.net
  2. 2. Agenda  What is it?  Old features done better  New features  Why scala?
  3. 3. What is it?  JVM language  Object-functional  Scripting  Java compatible  CONCISE
  4. 4. Old features done better  Syntax  Classes and Objects  Basic Types and Operations  Built-in Control Structures(if, while, switch)  Packages and Imports  Assertions and Unit Testing  Collections  Type Parameterization(Generics)
  5. 5. Syntax def max(ints: List[Int]): Int = { def max(x:Int, y:Int) : Int = if(x>y) x else y ints.fold(Int.MinValue)(max(_,_)) } val maxVar = max(List(1,2,3,4))  vals and vars  name: Type[typeParam]  def method(param1:pType, param2:pType): mType = { … }  array(2) instead of array[2]  not mandatory semicolon(;)  operators  Alternative method call “object method arg”  Type inference  Named parameters Integer max(List<Integer> ints){ Integer max = Integer.MIN_VALUE; for(Integer intEl : ints) if(intEl > max) max = intEl; return max; }
  6. 6. Classes and Objects  Singleton companion objects  Default constructor  Mandatory override modifier  One namespace for fields and methods class Rational(n: Int, d: Int) { require(d != 0) private val g = gcd(n.abs, d.abs) val numer = n / g val denom = d / g def this(n: Int) = this(n, 1) def + (that: Rational): Rational = new Rational( numer * that.denom + that.numer * denom, denom * that.denom ) def * (that: Rational): Rational = new Rational(numer * that.numer, denom * that.denom) override def toString = numer +"/"+ denom private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b) }  Evaluated at construction time  Default public modifier  No get/set convention  Complicated access modifiers you don’t want to know about
  7. 7. Basic Types and Operations  All the Java literals  (”””str”””) raw, multiline string(escapes doesn’t work)  Operators are methods, (1).+(2)  Object equality checked by ==, !=, not by .equals()  Reference equality checked by eq() method  foo(bar) is equal to foo.apply(bar)  Rich primitive types by implicit conversion  Any, AnyRef, Nothing
  8. 8. Built-in Control Structures(if, while, switch)  They return values!  Complicated for expression  Producing collections with for and yield  Catch with pattern matching  match – switch on steroids  No break and continue println(if (!args.isEmpty) args(0) else "default.txt") def grep(pattern: String) = for ( file <- filesHere if file.getName.endsWith(".scala"); line <- fileLines(file) if line.trim.matches(pattern) ) yield (file +": "+ line.trim) try { val f = new FileReader("input.txt") // Use and close file } catch { case ex: FileNotFoundException => // Handle missing file case ex: IOException => // Handle other I/O error } def describe(x: Any) = x match { case 5 => "five" case true => "truth" case "hello" => "hi!" case Nil => "the empty list" case _ => "something else" }
  9. 9. Packages and Imports  Java-like or C#-like packages  Imports can be declared anywhere  And are much more powerful package bobsrockets { package navigation { // In package bobsrockets.navigation class Navigator package tests { // In package bobsrockets.navigation.tests class NavigatorSuite } } } // easy access to Fruit import bobsdelights.Fruit // easy access to all members of bobsdelights import bobsdelights._ // easy access to all members of Fruits import bobsdelights.Fruits._ //import only Apple and Orange import Fruits.{Apple, Orange} //import all Fruits but Orange and rename Apple to McIntosh import Fruits.{Apple => McIntosh, Orange =>_, _}
  10. 10. Assertions and Unit Testing  Static assert() and non-static ensuring()  JUnit, TestNG, ScalaTest, specs import org.specs._ import Element.elem object ElementSpecification extends Specification { "A UniformElement" should { "have a width equal to the passed value" in { elem('x', 2, 3).width must be_==(2) } "have a height equal to the passed value" in { elem('x', 2, 3).height must be_==(3) } "throw an IAE if passed a negative width" in { elem('x', -2, 3) must throwA[IllegalArgumentException] } } }
  11. 11. Collections  Defaults are immutable!  Tuples  Sequences(Arrays, Lists, ArrayBuffers, ListBuffers)  map, flatMap, filter, collect, fold, …  Set, Map, MutableSet, MutableMap val tuple = (1, “hello”, 3.1) val (integer, str, dbl) = tuple Array(1.0, 2.0, 3.0) List(1, 2, 3, 4) Set(‘a’, ‘b’, ‘c’) Map("hi" -> 2, "there" -> 5)
  12. 12. Type Parameterization(Generics)  Types and type parameters are guessed if possible(target typing)  No raw types  Generic types have by default nonvariant (or, “rigid”) subtyping  Lower and upper bounds scala> val q = Queue(1, 2, 3) q: Queue[Int] = Queue(1, 2, 3) def doesNotCompile(q: Queue) {} //variance trait Q[T] {…} // nonvariant, Q[String] is not instance of Q[AnyRef] trait Q[+T] {…} // covariant, Q[String] is instance of Q[AnyRef] trait Q[-T] {…} // contravariant, Q[AnyRef] is instance of Q[String] class Queue[+T] (private val leading: List[T], private val trailing: List[T] ) { def enqueue[U >: T](x: U) = new Queue[U](leading, x :: trailing) // ... } def orderedMergeSort[T <: Ordered[T]](xs: List[T]): List[T] = {…}
  13. 13. New features  Scripting  Functional/immutable objects  Functions and Closures  Traits  Case Classes, Pattern Matching and Extractors  Implicit Conversions and Parameters  Working with XML  Actors and Concurrency
  14. 14. Scripting  Scala console  Script files  Good debug/testing tool #!/bin/sh exec scala "$0" "$@" !# // Say hello to the first argument println("Hello, "+ args(0) +"!") $ scala Welcome to Scala version 2.8.1. Type in expressions to have them evaluated. Type :help for more information. scala> 1 + 2 res0: Int = 3 scala> res0 * 3 res1: Int = 9
  15. 15. Functional/immutable objects  Matter of convention  No mutable state(vals of immutable types only)  “Mutating” methods return new object  Mutable alternatives(builders)  + Easier to reason about  + Pass freely around the system  + Thread safe  + Safe hash keys  - COPY
  16. 16. Functions and Closures  Methods  Nested/local functions  Function literals and values(first-class and higher-class)  Placeholder syntax  Closures  Repeated parameters  Named arguments  Default values  Tail recursion – no stack overflow and overhead scala> var increase = (x: Int) => x + 1 increase: (Int) => Int = <function1> scala> increase(10) res0: Int = 11 val someNumbers = List(11, 10, 5, 0, 5, 10) someNumbers.foreach((x: Int) => println(x)) someNumbers.filter(x => x > 0) someNumbers.map(_ * 2) val f = (_: Int) + (_: Int) ; f(5, 10) def sum(a: Int, b: Int, c: Int) = a + b + c val a = sum _ //partially applied function // also correct: val a = sum val b = sum(1, _: Int, 3) def makeIncreaser(more: Int) = (x: Int) => x + more //closure val inc1 = makeIncreaser(1) // inc1(10) = 11 val inc9999 = makeIncreaser(9999) //inc9999(-9) = 9990 def approximate(guess: Double): Double = if (isGoodEnough(guess)) guess else approximate(improve(guess)) // last call in body is recursive def div(x :Int, y :Int=1) { x*y } div( y=2 , x=3) div(3) scala> var increase = (x: Int) => x + 1 increase: (Int) => Int = <function1> scala> increase(10) res0: Int = 11 scala> var increase = (x: Int) => x + 1 increase: (Int) => Int = <function1> scala> increase(10) res0: Int = 11 scala> var increase = (x: Int) => x + 1 increase: (Int) => Int = <function1> scala> increase(10) res0: Int = 11 scala> var increase = (x: Int) => x + 1 increase: (Int) => Int = <function1> scala> increase(10) res0: Int = 11
  17. 17. Traits  Interfaces on steroids  Multiple inheritance  Linear order  Order of mixins is important! abstract class IntQueue { def get(): Int def put(x: Int) } class BasicIntQueue extends IntQueue { private val buf = new ArrayBuffer[Int] def get() = buf.remove(0) def put(x: Int) { buf += x } } 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) } } val queue = (new BasicIntQueue with Incrementing with Filtering) • If the behavior will not be reused, then make it a concrete class • If it might be reused in multiple, unrelated classes, make it a trait. • If you want to inherit from it in Java code, use an abstract class. • If you plan to distribute it in compiled form … its more complicated • If efficiency is very important, lean towards using a class. • If you still do not know, start with a trait.
  18. 18. Case Classes, Pattern Matching and Extractors abstract class Expr case class Var(name: String) extends Expr case class Number(num: Double) extends Expr case class UnOp(operator: String, arg: Expr) extends Expr case class BinOp(operator: String, left: Expr, right: Expr) extends Expr  A bit like enums  Automatically added factory method, toString, hashCode, equals, copy  Deep matches  Sealed classes  Subclasses in the same file  Matching coverage check  Extractors – allows you to treat class like a case class def simplifyAll(expr: Expr): Expr = expr match { case UnOp("", UnOp("", e)) => simplifyAll(e) // ‘’is its own inverse case BinOp("+", e, Number(0)) => simplifyAll(e) // ‘0’ is a neutral element for ‘+’ case BinOp("*", e, Number(1)) => simplifyAll(e) // ‘1’ is a neutral element for ‘*’ case UnOp(op, e) => UnOp(op, simplifyAll(e)) case BinOp(op, l, r) => BinOp(op, simplifyAll(l), simplifyAll(r)) case _ => expr } def describe(x: Any) = x match { case 5 => "five" case true => "truth" case "hello" => "hi!" case Nil => "the empty list" case _ => "something else" } object EMail { // The injection method (optional) def apply(user: String, domain: String) = user +"@"+ domain // The extraction method (mandatory) def unapply(str: String): Option[(String, String)] = { val parts = str split "@" if (parts.length == 2) Some(parts(0), parts(1)) else None } }
  19. 19. Implicit Conversions and Parameters  Implicit conversion  Only definitions marked implicit are available  An inserted implicit conversion must be in scope as a single identifier, or be associated with the source or target type of the conversion.  One-at-a-time Rule: Only one implicit is tried  Whenever code type checks as it is written, no implicits are attempted.  Implicit parameters implicit def function2ActionListener(f: ActionEvent => Unit) = new ActionListener { def actionPerformed(event: ActionEvent) = f(event) } class PreferredPrompt(val preference: String) object Greeter { def greet(name: String)(implicit prompt: PreferredPrompt) { println("Welcome, "+ name +". The system is ready.") println(prompt.preference) } } object JoesPrefs { implicit val prompt = new PreferredPrompt("Yes, master> ") } import JoesPrefs._ Greeter.greet("Joe")
  20. 20. Working with XML  XML literals  Compiled Xpath-like syntax  Pattern matching scala> val yearMade = 1955 scala> <a> { if (yearMade < 2000) <old>{yearMade+”r.”}</old> else xml.NodeSeq.Empty } </a> scala> <a><b><c>hello</c></b></a> "b" res10: scala.xml.NodeSeq = <b><c>hello</c></b> scala> <a><b><c d="world">hello</c></b></a> "c" "@d" res12: scala.xml.NodeSeq = world abstract class CCTherm { ... def toXML = <cctherm> <description>{description}</description> <yearMade>{yearMade}</yearMade> <dateObtained>{dateObtained}</dateObtained> <bookPrice>{bookPrice}</bookPrice> <purchasePrice>{purchasePrice}</purchasePrice> <condition>{condition}</condition> </cctherm> } abstract class CCTherm { ... def fromXML(node: scala.xml.Node): CCTherm = new CCTherm { val description = (node "description").text val yearMade = (node "yearMade").text.toInt val dateObtained = (node "dateObtained").text val bookPrice = (node "bookPrice").text.toInt val purchasePrice = (node "purchasePrice").text.toInt val condition = (node "condition").text.toInt }}
  21. 21. Actors and Concurrency  Anti „synchronized” way  Actor – thread + mailbox + actions  Good style:  Actors should not block  Communicate only via messages  Prefer immutable messages  Akka  Typesafe actors comming object NameResolver extends Actor { import java.net.{InetAddress, UnknownHostException} def act() { react { case (name: String, actor: Actor) => actor ! getIp(name) act() case "EXIT" => println("Name resolver exiting.") // quit case msg => println("Unhandled message: "+ msg) act() } } def getIp(name: String): Option[InetAddress] = { try { Some(InetAddress.getByName(name)) } catch { case _:UnknownHostException => None } } } scala> NameResolver.start() res0: scala.actors.Actor = NameResolver$@90d6c5 scala> NameResolver ! ("www.scalalang.org", self) scala> self.receiveWithin(0) { case x => x } res2: Any = Some(www.scalalang.org/128.178.154.102) scala> NameResolver ! ("wwwwww.scalalang.org", self) scala> self.receiveWithin(0) { case x => x } res4: Any = None
  22. 22. Why scala?  Conciseness  Immutability  Modernity  Convenience
  23. 23. References  Programming in Scala  Free at http://www.artima.com/pins1ed/  Scala for Java Programmers Tutorial  http://docs.scala-lang.org/tutorials/scala-for-java-programmers.html

×