scala uma poderosa linguagem para a jvm
DESCRIPTION
Palestra VI Workshop de TI - COTEMIGTRANSCRIPT
Scala
Uma poderosa linguagem para a JVM
Isaías Cristiano BarrosoStrategia Tecnologia
29 de Maio de 2012
Martin OderskyEPFL - École polytechnique fédérale de Lausanne
Criador da linguagem Scala
Compilador de Referência JAVA
Co-autor Java Generics
"If I were to pick a language to use today other than Java,
it would be Scala."
-- James Gosling, criador do Java
Scala – O que disse James Gosling?
Scala – Visão Geral
Compatibilidade com a JVM (JDK 1.5+)
Linguagem funcional
Empresa Typesafe (www.typesafe.com) mantemjunto a comunidade a linguagem Scala.
Scala – Comparação de Byte Code
class Hello { def sayHello(name: String):String = { "Hello " + name }}
public class Hello { public String sayHello(String name){ return "Hello " + name; }}
Código JAVA vs Scala
Scala – Comparação de Byte Code
public class Hello extends Object implements scala.ScalaObject{public java.lang.String sayHello(java.lang.String); Code: 0: new #7; //class scala/collection/mutable/StringBuilder 3: dup 4: invokespecial #11; //Method scala/collection/mutable/StringBuilder."<init>":()V 7: ldc #14; //String Hello 9: invokevirtual #18; //Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder; 12: aload_1 13: invokevirtual #18; //Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder; 16: invokevirtual #22; //Method scala/collection/mutable/StringBuilder.toString:()Ljava/lang/String; 19: areturnpublic Hello(); Code: 0: aload_0 1: invokespecial #30; //Method java/lang/Object."<init>":()V 4: return}
public class Hello extends java.lang.Object{public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return
public java.lang.String sayHello(java.lang.String); Code: 0: new #2; //class java/lang/StringBuilder 3: dup 4: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V 7: ldc #4; //String Hello 9: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 12: aload_1 13: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 16: invokevirtual #6; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 19: areturn
}
Scala – Orientada a Objetos
Cada valor é um objeto
Scala – Orientada a Objetos
scala> val a = 10a: Int = 10
scala> a.% & * + - / > >= >> >>> ^ asInstanceOf isInstanceOf toByte toChar toDouble toFloat toInt toLong toShort toString unary_+ unary_- unary_~ |
scala> a.+(10)res0: Int = 20
scala> a + 10res1: Int = 20
Cada valor é um objeto
Classes
Scala – Orientada a Objetos
class Point(xc: Int, yc: Int) { var x: Int = xc var y: Int = yc def move(dx: Int, dy: Int) { x = x + dx y = y + dy } override def toString(): String = "(" + x + ", " + y + ")";}
scala> val p = new Point(10, 20)p: Point = (10, 20)
scala> pres0: Point = (10, 20)
Classes (Scala vs JAVA)
Scala – Orientada a Objetos
class Point(xc: Int, yc: Int) { var x: Int = xc var y: Int = yc def move(dx: Int, dy: Int) { x = x + dx y = y + dy } override def toString(): String = "(" + x + ", " + y + ")";}
public class Point {int x;int y;Point(int xc, int yc){
x = xc;y = yc;
}public void move(int dx, int dy){
x = x + dx;y = y + dy;
}public String toString() {
return "(" + x + ", " + y + " )";}
}
Traits
Utilizadas para definir tipos e métodos suportados de um objeto
Similar as interfaces JAVA
Podem ser parcialmente implementadas
Não tem parâmetros para construtores
Scala – Orientada a Objetos
Traits
Scala – Orientada a Objetos
trait Similarity { def isSimilar(x: Any): Boolean def isNotSimilar(x: Any): Boolean = !isSimilar(x)}
class Point(xc: Int, yc: Int) extends Similarity { var x: Int = xc var y: Int = yc def isSimilar(obj: Any) = obj.isInstanceOf[Point] && obj.asInstanceOf[Point].x == x}
object TraitsTest extends Application { val p1 = new Point(2, 3) val p2 = new Point(2, 4) val p3 = new Point(3, 3) println(p1.isNotSimilar(p2)) // false println(p1.isNotSimilar(p3)) // true println(p1.isNotSimilar(2)) // true}
“object”
Equivalente a uma Singleton class to Java
Scala – Orientada a Objetos
…
object TraitsTest extends Application { val p1 = new Point(2, 3) val p2 = new Point(2, 4) val p3 = new Point(3, 3) println(p1.isNotSimilar(p2)) // false println(p1.isNotSimilar(p3)) // true println(p1.isNotSimilar(2)) // true}
“Companion Object”
Mesmo nome da classeDefinido no mesmo arquivo da classePossui acesso a todos os membros da classeMuito utilizado como Factory
Scala – Orientada a Objetos
http://www.scala-lang.org/api
“Companion Object”
Scala – Orientada a Objetos
http://www.scala-lang.org/api
“object”
Scala – Orientada a Objetos
scala> val bd = BigDecimal("123.43")bd: scala.math.BigDecimal = 123.43
scala> val bd = BigDecimal(123.43)bd: scala.math.BigDecimal = 123.43
scala> val bd = BigDecimal.apply("123.43")bd: scala.math.BigDecimal = 123.43
scala> val bd = BigDecimal.apply(123.43)bd: scala.math.BigDecimal = 123.43
“apply Method”
“Case Class” Classes Scala como qualquer outra
Exportam seus parâmetros de construtores
Método apply criado automaticamente
Permite decomposição funcional através de “pattern matching”
Scala – Orientada a Objetos
“Case Class”
Scala – Orientada a Objetos
scala> abstract class Pessoadefined class Pessoa
scala> case class PessoaFisica(nome: String, idade: Int) extends Pessoadefined class PessoaFisica
scala> case class PessoaJuricia(nome: String, tempoAbertura: Int) extends Pessoa defined class PessoaJuricia
scala> val pf = PessoaFisica("Joao", 83)pf: PessoaFisica = PessoaFisica(Joao,83)
scala> val pj = PessoaJuridica("The Corp", 4)pj: PessoaJuridica = PessoaJuridica(The Corp,4)
scala> println(pf)PessoaFisica(Joao,83)
scala> println(pj)PessoaJuridica(The Corp,4)
toString implementado automaticamente
“Case Class”
Scala – Orientada a Objetos
scala> val x = PessoaFisica("Joao", 83)x: PessoaFisica = PessoaFisica(Joao,83)
scala> val y = PessoaFisica("Joao", 83)y: PessoaFisica = PessoaFisica(Joao,83)
scala> val z = PessoaFisica("Maria", 78)z: PessoaFisica = PessoaFisica(Maria,78)
scala> x == yres3: Boolean = true
scala> x == zres4: Boolean = false
equals implementado automaticamente
scala> val pf = PessoaFisica("Isaias")<console>:9: error: not enough arguments for method apply: (nome: String, idade: Int)PessoaFisica in object PessoaFisica.Unspecified value parameter idade. val pf = PessoaFisica("Isaias")
apply de case class em ação
“Pattern Matching”
Scala – Orientada a Objetos
def testPM(p: Pessoa){ p match { case PessoaFisica(nome, idade) => println("Nome: " + nome) println("Idade: " + idade) case PessoaJuridica(nome, tempo) => println("Nome: " + nome) println("Tempo: " + tempo) case _ => println("Tipo Nao Esperado") } }
“Sealed Case Class” scala> sealed abstract class Pessoadefined class Pessoa
High Order Functions (Funções podem receber e retornar funções)
Programação concorrente
Encoraja a utilização de variáveis imutáveis (var x val)
Estaticamente tipada
Scala – Linguagem Funcional
Scala – Linguagem Funcional
def fac(n : Int) = {var r = 1for (i <- 1 to n) r = r * i
r}
scala> fac(5)res0: Int = 120
def fac(n: Int): Int = if (n <= 0) 1
else n * fac(n – 1)
scala> fac(5)res0: Int = 120
Fatorial
Fatorial - Recursivo
Não Otimizado
Scala – Linguagem Funcional
def fac(n: Int): Int = if (n <= 0) 1
else n * fac(n – 1)
<console>:10: error: could not optimize @tailrec annotated method fac: it contains a recursive call not in tail position if (n <= 0) 1
else n * fac(n -1)
^
@tailrec def factorial(accumulator: Int, number: Int) : Int = { if(number == 1) return accumulator factorial(number * accumulator, number - 1) }
@tailrec
Fatorial – Tail Recursive
Otimizado
Scala – Linguagem Funcional
def factorial(number: Int) : Int = { def factorialWithAccumulator(accumulator: Int, number: Int) : Int = { if (number == 1) return accumulator else factorialWithAccumulator(accumulator * number, number - 1) } factorialWithAccumulator(1, number)}
Melhorando a função
Functionsdef <nome>(parametros) : <retorno>
Scala – Linguagem Funcional
def funcao1() { println(“Funcao sem parametro e sem retorno”)}
def funcao2(x: Int, y: String) { println(“Funcao com parametro e sem retorno”)}
def funcao3(x: Int, y: String) = {println(“Funcao com parametros e retorno implicito”)
“retorno”}
def funcao4(x: Int, y: String):String = {println(“Funcao com parametros e retorno explicito”)
“retorno”}
Funções Anônimas
Scala – Linguagem Funcional
scala> (x: Int) => x + 1res0: Int => Int = <function1>
scala> res0(1)res1: Int = 2
Funções como valoresscala> val inc = (x: Int) => x + 1inc: Int => Int = <function1>
scala> inc(10)res0: Int = 11
High Order Functions
Scala – Linguagem Funcional
scala> def soma(x:Int, y:Int):Int = { | x+y | }soma: (x: Int, y: Int)Int
scala> soma(10,20)res5: Int = 30
scala> def withLog(f:(Int, Int) => Int, x:Int, y:Int):Int = { | println("Iniciando execucao da funcao") | val result = f(x,y) | println("Finalizando Execucao") | result | }withLog: (f: (Int, Int) => Int, x: Int, y: Int)Int
scala> withLog(soma, 10, 20)Iniciando execucao da funcaoFinalizando Execucaores6: Int = 30
Querulous
Scala – Linguagem Funcional
queryEvaluator.transaction { transaction => transaction.select("SELECT ... FOR UPDATE", ...) transaction.execute("INSERT INTO users VALUES (?, ?)", 1, "Jacques") transaction.execute("INSERT INTO users VALUES (?, ?)", 2, "Luc")}//def transaction[T](f: Transaction => T) = { withTransaction { transaction => transaction.begin() try { val rv = f(transaction) transaction.commit() rv } catch { case e: Throwable => transaction.rollback() throw e } } } private def withTransaction[A](f: Transaction => A) = { database.withConnection { connection => f(new Transaction(queryFactory, connection)) } }
Implicit Parameters
Scala – Linguagem Funcional
scala> def addOne(implicit x:Int) = { | x+1 | }addOne: (implicit x: Int)Int
scala> addOne<console>:9: error: could not find implicit value for parameter x: Int addOne ^
scala> implicit val x = 10x: Int = 10
scala> addOneres1: Int = 11
scala> addOne(35)res2: Int = 36
Implicit Conversions
Scala – Linguagem Funcional
scala> class RichString(s:String)defined class RichString
scala> implicit def string2RichString(s:String) = new RichString(s)string2RichString: (s: String)RichString
scala> val x = "Isaias"x: java.lang.String = Isaias
scala> def printString(r: RichString) { | println(r) | }printString: (r: RichString)Unit
scala> printString(x)$line1.$read$$iw$$iw$RichString@6fafc4c2
scala>
Mixin Class Composition
Scala – Linguagem Funcional
abstract class AbsIterator { type T def hasNext: Boolean def next: T}
trait RichIterator extends AbsIterator { def foreach(f: T => Unit) { while (hasNext) f(next) }}
class StringIterator(s: String) extends AbsIterator { type T = Char private var i = 0 def hasNext = i < s.length() def next = { val ch = s charAt i; i += 1; ch }}
object StringIteratorTest { def main(args: Array[String]) { class Iter extends StringIterator(args(0)) with RichIterator val iter = new Iter iter foreach println }}
Lists
Scala – Collections
val numbers = List(1, 2, 3, 4)numbers: List[Int] = List(1, 2, 3, 4)
Setsscala> Set(1, 1, 2)res0: scala.collection.immutable.Set[Int] = Set(1, 2)
Scala – Collections
Tuplasscala> val hostPort = ("localhost", 80)hostPort: (String, Int) = (localhost, 80)
scala> hostPort._1res5: java.lang.String = localhost
scala> hostPort._2res6: Int = 80
Tuplas – Pattern MatchinghostPort match { case ("localhost", port) => ... case (host, port) => ...}
Scala – Collections
MapMap(1 -> 2)res0: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)
Map("foo" -> "bar")res0: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(foo -> bar)
Map(1 -> Map("foo" -> "bar"))res0: scala.collection.immutable.Map[Int,scala.collection.immutable.Map[java.lang.String,java.lang.String]] = Map(1 -> Map(foo -> bar))
Scala – Collections
Optionval map = Map("Hi" -> "Dan", "Hello" -> "Jane")val result = map.get( "Hello" )
result match { case None => println("No value found for key!") case Some(x) => print("Found value" + x)}
scala> map.get("NoKey")res5: Option[java.lang.String] = None
Scala – Collections
Functional Combinators“A saída de uma função será utilizada como entrada para outra
função”
scala> val numbers = List(1, 2, 3, 4)numbers: List[Int] = List(1, 2, 3, 4)
scala> numbers.map((i:Int) => i * 2)res0: List[Int] = List(2, 4, 6, 8)
scala> numbers.map(_ * 2)res1: List[Int] = List(2, 4, 6, 8)
scala> numbers.foreach((i: Int) => i * 2) // Sem retorno
scala> var value = 0value: Int = 0
scala> numbers.foreach((i: Int) => value = i*2)
scala> valueres1: Int = 28
Scala – Collections
Functional Combinators
scala> numbers.filter((i: Int) => i%2==0)res0: List[Int] = List(2, 4)
scala> def isEven(i: Int): Boolean = i % 2 == 0isEven: (i: Int)Boolean
scala> numbers.filter(isEven _)res2: List[Int] = List(2, 4)
scala> List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).partition((i: Int) => i > 5)res0: (List[Int], List[Int]) = (List(6, 7, 8, 9, 10),List(1, 2, 3, 4, 5))
scala> res0._1res1: List[Int] = List(6, 7, 8, 9, 10)
scala> res0._2res2: List[Int] = List(1, 2, 3, 4, 5)
Scala – Collections
Functional Combinators
scala> val numbers = List(1,2,3,4,5,6,7,8,9,10)numbers: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> numbers.find((i: Int) => i > 5)res5: Option[Int] = Some(6)
scala> numbers.drop(5)res0: List[Int] = List(6, 7, 8, 9, 10)
scala> numbers.dropWhile((i: Int) => i < 6)res0: List[Int] = List(6, 7, 8, 9, 10)
Scala – Collections
Functional Combinators
scala> numbers.foldLeft(0)((m: Int, n: Int) => m + n)res0: Int = 55
scala> numbers.foldLeft(0) { (m: Int, n: Int) => println("m: " + m + " n: " + n); m + n }m: 0 n: 1m: 1 n: 2m: 3 n: 3m: 6 n: 4m: 10 n: 5m: 15 n: 6m: 21 n: 7m: 28 n: 8m: 36 n: 9m: 45 n: 10res0: Int = 55
Scala – Collections
Functional Combinators
scala> numbers.foldRight(0)((m: Int, n: Int) => m + n)res0: Int = 55
scala> numbers.foldRight(0)((m: Int, n: Int) => println("m: " + m + " n: " + n); m + n)m: 10 n: 0m: 9 n: 10m: 8 n: 19m: 7 n: 27m: 6 n: 34m: 5 n: 40m: 4 n: 45m: 3 n: 49m: 2 n: 52m: 1 n: 54res0: Int = 55
Scala – Collections
Functional Combinators
scala> List(List(1, 2), List(3, 4)).flattenres0: List[Int] = List(1, 2, 3, 4)
scala> val nestedNumbers = List(List(1, 2), List(3, 4))nestedNumbers: List[List[Int]] = List(List(1, 2), List(3, 4))
scala> nestedNumbers.flatMap(x => x.map(_ * 2))res0: List[Int] = List(2, 4, 6, 8)
Scala – Collections
Functional Combinators
scala> val lista = List(p1, p2, p3)lista: List[Pessoa] = List(Pessoa(Joao,83), Pessoa(Maria,78), Pessoa(Isaias,33))
scala> lista.filter(pessoa => pessoa.idade > 70)res2: List[Pessoa] = List(Pessoa(Joao,83), Pessoa(Maria,78))
Scala – Collections
scala> List(10, 20, 30) |@| List(1, 2, 3) apply (_ * _)
Scalaz Combinator
res0: List[Int] = List(10, 20, 30, 20, 40, 60, 30, 60, 90)
Scala – Collections
Conversões Java / Scala
import scala.collection.JavaConversions._
val sl = new scala.collection.mutable.ListBuffer[Int] val jl : java.util.List[Int] = sl val sl2 : scala.collection.mutable.Buffer[Int] = jl assert(sl eq sl2)
scala.collection.Iterable <=> java.lang.Iterablescala.collection.Iterable <=> java.util.Collectionscala.collection.Iterator <=> java.util.{ Iterator, Enumeration }scala.collection.mutable.Buffer <=> java.util.Listscala.collection.mutable.Set <=> java.util.Setscala.collection.mutable.Map <=> java.util.{ Map, Dictionary }scala.collection.mutable.ConcurrentMap <=> java.util.concurrent.ConcurrentMap
Conversões Mão Dupla
Scala – Collections
Conversões Java / Scala
scala.collection.Iterable <=> java.lang.Iterablescala.collection.Iterable <=> java.util.Collectionscala.collection.Iterator <=> java.util.{ Iterator, Enumeration }scala.collection.mutable.Buffer <=> java.util.Listscala.collection.mutable.Set <=> java.util.Setscala.collection.mutable.Map <=> java.util.{ Map, Dictionary }scala.collection.mutable.ConcurrentMap <=> java.util.concurrent.ConcurrentMap
Conversões Mão Única
Scala – Actors
Scala Actors
Abstração em processos Assíncronos
Comunicação através de envio e recepção de mensagens
Tratamento de uma mensagem por vez
Melhor utilizado em cenários que podem ser divididos em várias etapas
Scala – Actors
Scala Actorsclass Ping(count: Int, pong: Actor) extends Actor { def act() { var pingsLeft = count - 1 pong ! Ping loop { react { case Pong => if (pingsLeft % 1000 == 0) println("Ping: pong") if (pingsLeft > 0) { pong ! Ping pingsLeft -= 1 } else { println("Ping: stop") pong ! Stop exit() } } } }}
Scala – Actors
Scala Actorsclass Pong extends Actor { def act() { var pongCount = 0 loop { react { case Ping => if (pongCount % 1000 == 0) println("Pong: ping "+pongCount) sender ! Pong pongCount += 1 case Stop => println("Pong: stop") exit() } } }}
object pingpong extends Application { val pong = new Pong val ping = new Ping(100000, pong) ping.start pong.start}
Scala – Actors
Akka Actors
Scala – Ferramentas de Teste
ScalaTest (http://www.scalatest.org)Test Driven Development (TDD) Behaviour-Driven Development (BDD) Funcional, integração e aceitação
import org.scalatest.FunSpec
class ExampleSpec extends FunSpec {
describe("A Stack") {
it("should pop values in last-in-first-out order") (pending)
it("should throw NoSuchElementException if an empty stack is popped") (pending) }}
Scala – Ferramentas de Teste
specs2 (http://etorreborre.github.com/specs2/) Testes unitários Testes de aceitação
import org.specs2.mutable._
class HelloWorldSpec extends Specification {
"The 'Hello world' string" should { "contain 11 characters" in { "Hello world" must have size(11) } "start with 'Hello'" in { "Hello world" must startWith("Hello") } "end with 'world'" in { "Hello world" must endWith("world") } } }
Scala – IDEs
http://scala-ide.org/
http://www.jetbrains.com/idea/
Scala – Ferramentas de Build
SBT (https://github.com/harrah/xsbt/wiki)
MAVEN (http://maven.apache.org/)
Scala – Frameworks Web (Full)
Scala – Frameworks Web Java Compatíveis com Scala
Spring MVC V-Raptor
http://www.contasrefeitas.com.br/
Scala – Twitter
Scala – Timeline Twitter
Mais de 100 milhões de usuários ativos
250 mil Tweets por dia3 mil tweets / segundo – Média diária5 mil tweets / segundo – PicoMais de 10 mil Tweets / segundo (Super Bowl)
Poll-based200 mil queries por segundoLatência 1 milesegundo na média
Buscas30 mil queries por segundo
https://github.com/twitter/finagle
Scala
Scala
Perguntas?
?