Arthur Felipe Bruno Pimentel Carlos Junior Mateus Araujo Scala.
Transcript of Arthur Felipe Bruno Pimentel Carlos Junior Mateus Araujo Scala.
Arthur FelipeBruno PimentelCarlos JuniorMateus Araujo
Scala
Roteiro
• Introdução e História da Linguagem• Sintaxe• Aplicações e futuro• Conclusão• Referências
Introdução e História da Linguagem
• O nome Scala significa “linguagem escalável”
• Projetada para integrar linguagem orientada a objetos e programação funcional
• Executado em plataforma Java• Mesmo modelo de compilação como Java
e C#
Introdução e História da Linguagem
• Recursos orientados a objetoso Cada valor é um objeto, onde seus
comportamentos são descritos por classeso Abstrações de classes
• Programação Funcionalo Definição de funçõeso Funções de ordem superioro Casamento de padrõeso Tipos algébricos
Introdução e História da Linguagem
• O design começou em 2001 na École Polytechnique Fédérale de Lausanne (EPFL) por Martin Odersky
• Foi liberado no fim de 2003 e início de 2004 na plataforma Java
• Em Junho de 2004 na plataforma .NET
Introdução e História da Linguagem
• Em 2009, Twitter mudou grande boa parte dos seus back-end do Ruby para Scala e pretende mudar o resto
• A Wattzon afirmou que toda a sua plataforma foi escrita em Scala
Por quê utilizar Scala?
Scala é Escalável
• Adequada para tarefas de qualquer tamanhooMuito pequenas (scripts)oMuito grandes (frameworks)
Scala é Multiplataforma
• Roda em vários ambienteso Java Virtual Machine (JVM)o Plataforma .NETo Java Platform, Micro Edition (Java ME)
Scala é Elegante
• Linguagem simples que une conceitos de OO e funcionaloFacilita a manutenção dos programasoUsa bibliotecas ao invés de outras
linguagens para desenvolver módulosespecíficos
oSimplicidade de funcional + poder de Objetos
Sintaxe
Variáveis e Valores
> var a = "Hello " a: java.lang.String = Hello> a = a + "World!"a: java.lang.String = Hello World!> println(a)Hello World!
Variáveis e Valores
> val b = "Bob Esponja" b: java.lang.String = Bob Esponja> b += " e Patrick"error: reassignment to val b += " e Patrick" ^
Inferência de tipos
> val t = 1 / 2t: Int = 0> val d: Double = 1 / 2f: Double = 0.0> val g : Double = 1.0 / 2.0g: Double = 0.5
Funções> def scale = 5 //Uma função constantescale: Int
> def square(x: Double) = x * x square: (Double)Double
> square(2)unnamed0: Double = 4.0
> def sumOfSquares(x: Double, y: Double) = square(x) + > square(y)sumOfSquares: (Double,Double)Double
Funções> def min (x:Int, y:Int) = {> if (x < y) x> else y > }min: (Int,Int)Int> def invert (x: Int) = -xinvert: (Int)Int> def invert (x: Int) : Int = { return -x }invert: (Int)Int
Tudo é um objetoNão existem primitivas. > 1233.hashCoderes0: Int = 1233 Toda operação é uma chamada de uma função: > 2 + 2 == 2.+(2)res4: Boolean = true > Console.println("Ronaldo!")Ronaldo!> Console println "Brilha muito no Corinthians"...
Estruturas de controle
Praticamente todas as estruturas de controle são também expressões:> val x = if (0 < 1) 10 else 20 x: Int = 10> val y = if (0 < 1) 10 //sem o else y: Unit = () //Unit é o 'Null' em Scala
Estruturas de controleCompreensões utilizando 'for' > val places = List("Olinda", "Recife", "São Paulo", "Manaus")> for (place <- places)> println(place)Olinda \n Recife \n São Paulo \n Manaus \n > val places2 = List("Olinda", "Recife", "São Paulo", "Manaus","São Vicente")> for (place <- places2 if place.contains("São"))> println(place)São Paulo \n São Vicente \n
Estruturas de controleUtilizando `yield` para passagem de valores:
val dogBreeds = List("Doberman", "Yorkshire Terrier", "Dachshund", "Scottish Terrier", "Great Dane", "Portuguese Water Dog") val filteredBreeds = for { breed <- dogBreeds if breed.contains("Terrier") if !breed.startsWith("Yorkshire") } yield breed
Estruturas de controle
Utilizando ranges. > for (i <-1 to 10) println(i)1 \n 2 \n ...
Utilizando `while`
> var count = 0> while (count < 10) {> count += 1> println(count)>}
Funções como objetos
Somatório:> def sum(f: Int => Int, a: Int, b: Int): Int = > if (a > b) 0 else f(a) + sum(f, a + 1, b)sum: ((Int) => Int,Int,Int)IntUtilizando uma função anônima:> def sumSquares(a:Int, b:Int):Int = sum(((x:Int) => x*x),a,b)sumSquares: (Int,Int)Int> sumSquares(1,10)res1: Int = 385
Funções como objetos
Currying:
> def filter(xs: List[Int], p: Int => Boolean): List[Int] => if (xs.isEmpty) xs> else if (p(xs.head)) xs.head :: filter(xs.tail, p)> else filter(xs.tail, p)filter: (List[Int],(Int) => Boolean)List[Int]
> def modN(n: Int)(x: Int) = ((x % n) == 0)modN: (Int)(Int)Boolean
> filter(List(1,2,3,4,5,6,7,8,9,0),modN(2))List[Int] = List(2, 4, 6, 8, 0)
Exemplo: Quicksort (funcional) def sort(xs: Array[Int]): Array[Int] = { if (xs.length <= 1) xs else { val pivot = xs(xs.length / 2) Array.concat( sort(xs filter (pivot >)), xs filter (pivot ==), sort(xs filter (pivot <))) } }
Para testar:> sort(Array(15,3,44,457,18))
Exemplo: Quicksort (imperativo)
def sort(xs: Array[Int]) { def swap(i: Int, j: Int) { val t = xs(i); xs(i) = xs(j); xs(j) = t } def particionar(l: Int, r: Int) {...} particionar(0, xs.length - 1) }
Para testar:> sort(Array(15,3,44,457,18))
Exemplo: Quicksort (imperativo) def particionar(l: Int, r: Int) { val pivot = xs((l + r) / 2) var i = l; var j = r while (i <= j) { while (xs(i) < pivot) i += 1 while (xs(j) > pivot) j -= 1 if (i <= j) { swap(i, j) i += 1 j -= 1 } } if (l < j) particionar(l, j) if (j < r) particionar(i, r) }
Pattern Matching
> def matchTest(x: Int): String = x match {> case 1 => "one"> case 2 => "two"> case _ => "many"> }matchTest: (Int)String
> println(matchTest(3))many
Pattern Matching
> val willWork = List(1, 3, 23, 90)> val willNotWork = List(4, 18, 52)> val empty = List()> for (l <- List(willWork, willNotWork, empty)) {> l match {> case List(_, 3, _, _) => println("Four elements, with the > 2nd being '3'.")> case List(_*) => println("Any other list with 0 or more > elements.")> }>}
Listas
> val l1 = List(1, 2, 3) > val l2: List[Int] = 4 :: 5 :: 6 :: Nil > val l3 = l1 ::: l2 l1: List[Int] = List(1, 2, 3)l2: List[Int] = List(4, 5, 6)l3: List[Int] = List(1, 2, 3, 4, 5, 6)> l3.foreach (n => println(n)) 1 \n 2 \n ...
ListasAlguns métodos para se trabalhar com listas: val lista = "Will" :: "fill" :: "until" :: Nillista(2) //retorna o segundo elemento da listalista.count(s => s.length == 4)lista.drop(2) //lista sem os 2 primeiros elementoslista.exists(s => s == "until")lista.filter(s => s.length == 4)lista.map(s => s + "y")lista.isEmpty
Tuplas
> def tupleator(x1: Any, x2: Any, x3: Any) = (x1, x2, x3)
> val t = tupleator("Hello", 1, 2.3)> println( "Print the whole tuple: " + t )> println( "Print the first item: " + t._1 )> println( "Print the second item: " + t._2 )> println( "Print the third item: " + t._3 )
> val (t1, t2, t3) = tupleator("World", '!', 0x22)> println( t1 + " " + t2 + " " + t3 )
Mapas
> val stateCapitals = Map("PE" -> "Recife", "AL" -> "Maceió")stateCapitals: scala.collection.immutable (...)> println("Imprime os objetos dentro de Options")> println( "PE: " + stateCapitals.get("PE") )> println( "SP: " + stateCapitals.get("SP") )"Imprime os objetos dentro de Options"PE: Some(Recife)SP: None
Mapas
> println( "Retirando o objeto da Option...")> println( "PE: " + stateCapitals.get("PE").get )> println( "SP: " + > stateCapitals.get("SP").getOrElse("Oops2!") ) Retirando o objeto da Option...PE: RecifeSP: Oops2!
Arrays
> val names = Array("José","Maria")> names(0) = "João"
> val cities = new Array[String](2)> cities(0) = "Recife"> cities(1) = "Olinda"
> cities.foreach{println}
Classes e Objetos • Em Scala todo valor é um objeto.
• Tipos e comportamentos de objetos são descritos por
classes e traits. • Todos os valores são instâncias de classes.
Hierarquia de Classes
Classes e ObjetosClasses são templates estáticos que podem ser instanciados em vários objetos durante o tempo de execução. 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 + ")";}
Classes e ObjetosObject: classe com uma única instância(singleton). Classes são instanciadas com a primitiva new. object Classes { def main(args: Array[String]) { val pt = new Point(1, 2) val pt2 = new Point(3,4) println(pt, pt2) }}
Classes e Objetos
• Classes podem extender outras classes. • Métodos podem ser sobrescritos.
class ColorPoint(u: Int, v: Int, c: String) extends Point(u, v) { val color: String = c def compareWith(pt: ColorPoint): Boolean = (pt.x == x) && (pt.y == y) && (pt.color == color) override def move(dx: Int, dy: Int): ColorPoint = new ColorPoint(x + dy, y + dy, color)}
Classes e Objetos
Adicionando algumas restrições em classes: class Person(name: String, age: Int) { if (age < 0) throw new IllegalArgumentException def sayHello() { println("Hello, " + name) }} class Adult(name: String, age: Int) { require (age >= 18) def sayHello() { println("Já pode tomar cana, " + name) }}
Case Classes
São classes que exportam seus parâmetros de construtor. Fornecem um mecanismo de decomposição recursiva através de pattern matching. abstract class Termcase class Var(name: String) extends Termcase class Fun(arg: String, body: Term) extends Termcase class App(f: Term, v: Term) extends Term
Case Classesobject TermTest extends Application { def printTerm(term: Term) { term match { case Var(n) => print(n) case Fun(x, b) => print("^" + x + ".") printTerm(b) case App(f, v) => Console.print("(") printTerm(f) print(" ") printTerm(v) print(")") } }
Traits
Similares a interface em java. Permitem implementação parcial. trait Similaridade { def eSimilar(x:Any) : Boolean def naoSimilar(x:Any) : Boolean = !eSimilar(x)}
TraitsO metodo "naoSimilar" não precisa ser implementado pelas classes que extenderem o trait Similaridade. Exemplo: class Ponto(xc: Int, yc: Int) extends Similaridade { var x: Int = xc var y: Int = yc def eSimilar(obj: Any) = obj.isInstanceOf[Ponto] && obj.asInstanceOf[Ponto].x == x}
Composição MixinEspecie de herança multipla. Herda os métodos da superclasse + os novos métodos das classes mixins. Mixin: classe que aparece associada á palavra with na declaração de classes. Apenas trait pode ser usada como mixin.
Composição Mixinabstract 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 } }
Generics
class Pilha[T] { var elems: List[T] = Nil def push(x: T) { elems = x :: elems } def top: T = elems.head def pop() { elems = elems.tail }} ...val pilha = new Pilha[Int]...
Estendendo a linguagem
Escalabilidade -> Extensibilidade
Exemplo: Tipos numéricos • Linguagens atuais suportam int, float, double, long...• Deveriam suportar também BigInt, BigDecimal,
Complex... ?• Existem boas razões para suportar todos eles, mas
tornaria a linguagem muito complexa! Solução: Permitir que os usuários extendam a linguagem conforme suas necessidades!
Definindo um novo tipo de dados
class Rational(n: Int, d: Int) {private def gcd(x: Int, y: Int): Int = {...}private val g = gcd(n, d)val numer: Int = n/gval denom: Int = d/g def + (that: Rational) = new Rational(numer * that.denom + that.numer * denom, denom * that.denom)def - (that: Rational) = new Rational(numer * that.denom - that.numer * denom, denom * that.denom)...}
Definindo novas estruturas de controle
object TargetTest1 extends Application { def whileLoop(cond: => Boolean)(body: => Unit): Unit = if (cond) { body whileLoop(cond)(body) } var i = 10 whileLoop (i > 0) { println(i) i -= 1 }}
Definindo novas estruturas de controle
Utilizando using para controle de recursos:
using (new BufferedReader(new FileReader(path))) { f => println(f.readLine())}
Ao invés de:
val f = new BufferedReader(new FileReader(path))try { println(f.readLine())} finnaly { if (f != null) f.close()}
Definindo novas estruturas de controle
Implementação:
def using[T <: {def close() } ] (resource: T) (block: T => Unit) { try { block(resource) } finally { if (resource != null) resource.close() }}
Concorrência
Concorrência
• Gerenciar concorrência não é tarefa fácil em muitas linguagenso Como lidar com acesso simultâneo a memória, disco,
variáveis e filas de mensagens?o Como saber o comportamento do programa com
5,10,500 processos simultâneos?o Como gerenciar locks e notifiers?
Concorrência
Infelizmente gerenciar concorrência em outras linguagens traz mais perguntas do que repostas.
Felizmente, Scala oferece uma abordagem elegante e
flexível para estes problemas.... Actors
Concorrência
Actors na teoria: • São objetos que recebem mensagens e tomam ações
baseados nelas.• Um Actor pode enviar a mensagem para outro ou criar
um novo Actor de acordo com a mensagem recebida.• Não possuem sequência ou ordem de ações, não
compartilham estado global.
Concorrência
Actors na prática:• Objeto que herda de scala.actors.Actor• Principais métodos:
ConcorrênciaActors na prática:import scala.actors.Actorclass Redford extends Actor {def act() {println("A lot of what acting is, is paying attention.")}}val robert = new Redfordrobert.start
Concorrência
Actors na prática: import scala.actors.Actorimport scala.actors.Actor._
val paulNewman = actor {println("To be an actor, you have to be a child.")}
Concorrência
Actors na prática: Enviando mensagem import scala.actors.Actorimport scala.actors.Actor._val fussyActor = actor {loop {receive {case s: String => println("I got a String: " + s)case i: Int => println("I got an Int: " + i.toString)case _ => println("I have no idea what I just got.")}}}fussyActor ! "hi there"fussyActor ! 23
fussyActor ! 3.33
Concorrência
Actors na prática (MailBox):import scala.actors.Actorimport scala.actors.Actor._val countActor = actor {loop {react {case "how many?" => {println("I've got " + mailboxSize.toString + " messages in my mailbox.")}}}}countActor ! 1countActor ! 2countActor ! 3countActor ! "how many?"countActor ! "how many?"countActor ! 4countActor ! "how many?"
Concorrência
Actors na prática:• Aplicação exemplo Loja do barbeiro
dorminhoco.
Aplicações e futuro• Scala se encaixa no futuro multiplataforma
e multilinguagem das linguagens de programação
• Scala é uma linguagem fácil de aprender para programadores Java-like.
• Scala oferece mecanismos flefíveis para tratar concorrência e paralelismo.
Aplicações e futuro• Principais aplicações:
o Kestrel Substituiu o Starling (servidor de filas utilizado pelo
Twitter) Agilizou o processo de entrega de mensagens no Twitter e
resolveu antigos problemas de infra do Starlingo Lift
Framework para criação de sistemas Web baseado em Scala. Parecido com JSF, JBoss Seam.
Como é baseado em Scala resolve facilmente problemas de Java e oferece um novo ponto de vista sobre construção de sistemas Web.
Conclusão
• Eficiente tanto para linguagens orientados a objetos quanto funcionais
• Independência de plataforma • É escalável: atende à demanda dos
usuários• Linguagem de propósito geral com forma
elegante, concisa e type-safe
Referências
• http://www.scala-lang.org/
• http://en.wikipedia.org/wiki/Scala_(programming_language)
• http://pt.wikipedia.org/wiki/Scala_(linguagem_de_programação)
• Tutorial Scala - http://www.scala-lang.org/docu/ files/ScalaTutorial.pdf
Dúvidas?
Arthur FelipeBruno PimentelCarlos JuniorMateus Araujo