Apresentação:Ana Catarina M. F. de Araujo Carla Regina Silva Araujo
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