Introdução a Scala [GeekieTalk]
-
Upload
nicolau-werneck -
Category
Engineering
-
view
176 -
download
4
Transcript of Introdução a Scala [GeekieTalk]
Introdução a Scala
Nicolau L. Werneck
Geekie
Geekie, São Paulo11 de Março de 2015
Roteiro
A vida, o universo e tudo maisPorque Scala?Aula de Scala
1 / 42
O Programador Humilde
Minha primeira observação é que,apesar da atividade do programadorterminar quando ele constrói umprograma correto, é o processo queocorre sob o controle do programa queé o verdadeiro tema de seu trabalho,porque é este processo que produz osefeitos desejados, é este processo queem seu comportamento dinâmico devesatisfazer as especificações desejadas.
Ainda assim, uma vez que o programa foi feito, a condução doprocesso correspondente é delegado à máquina.
2 / 42
O Programador HumildeMinha segunda observação e que nossos poderes intelectuaissão voltados para dominar relações estáticas, e nossos poderes devisualizar processos evoluindo no temposão relativamente mal-desenvolvidos. Poristo devemos, como sábios programadorescientes de nossas limitações, fazer nossoabsoluto melhor para reduzir a separaçãoconceitual entre o programa estático e oprocesso dinâmico, para tornar tão trivialquanto possível a correspondência entreo programa, espalhado no espaço dostextos, e o processo, espalhado no tempo.
— EWD215 “A case against the go-to statement”, Comm. ACM 11 (1968)
3 / 42
O Programador Humilde
Nós devemos fazer um trabalhobem melhor de programação, desde quesaibamos: abordar a tarefa com uma completaapreciação de sua tremenda dificuldade;nos ater a linguagens de programaçãomodestas e elegantes; respeitar os limitesintrínsecos da mente humana, e abordar atarefa como um Programador Muito Humilde.
— Dijkstra, EWD340 “The Humble Programmer” (1972)
4 / 42
O Programador Humilde
Nós devemos fazer um trabalhobem melhor de programação, desde quesaibamos: abordar a tarefa com uma completaapreciação de sua tremenda dificuldade;nos ater a linguagens de programaçãomodestas e elegantes; respeitar os limitesintrínsecos da mente humana, e abordar atarefa como um Programador Muito Humilde.
— Dijkstra, EWD340 “The Humble Programmer” (1972)
4 / 42
O Programador HumildeHumilde mas ambicioso...Programas devem ser compostos corretamente, e nãoapenas depurados até a correção.
Benefícios da humildade em desenvolvimento de software:Lidar com suas limitações cognitivas comoprogramadorAprender novas técnicasTestar novas ferramentasAprender o que o usuário precisa (modelagem)Descobrir o que ninguém nem desconfiava
5 / 42
O Programador HumildeHumilde mas ambicioso...Programas devem ser compostos corretamente, e nãoapenas depurados até a correção.
Benefícios da humildade em desenvolvimento de software:Lidar com suas limitações cognitivas comoprogramadorAprender novas técnicasTestar novas ferramentasAprender o que o usuário precisa (modelagem)Descobrir o que ninguém nem desconfiava
5 / 42
O Programador HumildeHumilde mas ambicioso...Programas devem ser compostos corretamente, e nãoapenas depurados até a correção.
Benefícios da humildade em desenvolvimento de software:Lidar com suas limitações cognitivas comoprogramadorAprender novas técnicasTestar novas ferramentasAprender o que o usuário precisa (modelagem)Descobrir o que ninguém nem desconfiava
5 / 42
O Programador HumildeHumilde mas ambicioso...Programas devem ser compostos corretamente, e nãoapenas depurados até a correção.
Benefícios da humildade em desenvolvimento de software:Lidar com suas limitações cognitivas comoprogramadorAprender novas técnicasTestar novas ferramentasAprender o que o usuário precisa (modelagem)Descobrir o que ninguém nem desconfiava
5 / 42
O Programador HumildeHumilde mas ambicioso...Programas devem ser compostos corretamente, e nãoapenas depurados até a correção.
Benefícios da humildade em desenvolvimento de software:Lidar com suas limitações cognitivas comoprogramadorAprender novas técnicasTestar novas ferramentasAprender o que o usuário precisa (modelagem)Descobrir o que ninguém nem desconfiava
5 / 42
O Programador HumildeHumilde mas ambicioso...Programas devem ser compostos corretamente, e nãoapenas depurados até a correção.
Benefícios da humildade em desenvolvimento de software:Lidar com suas limitações cognitivas comoprogramadorAprender novas técnicasTestar novas ferramentasAprender o que o usuário precisa (modelagem)Descobrir o que ninguém nem desconfiava
5 / 42
O Programador HumildeHumilde mas ambicioso...Programas devem ser compostos corretamente, e nãoapenas depurados até a correção.
Benefícios da humildade em desenvolvimento de software:Lidar com suas limitações cognitivas comoprogramadorAprender novas técnicasTestar novas ferramentasAprender o que o usuário precisa (modelagem)Descobrir o que ninguém nem desconfiava
5 / 42
O Programador HumildeHumilde mas ambicioso...Programas devem ser compostos corretamente, e nãoapenas depurados até a correção.
Benefícios da humildade em desenvolvimento de software:Lidar com suas limitações cognitivas comoprogramadorAprender novas técnicasTestar novas ferramentasAprender o que o usuário precisa (modelagem)Descobrir o que ninguém nem desconfiava
5 / 42
Abstrações e modelagem
Uma linguagem de programação servea dois propósitos relacionados: elaprovê um veículo para o programadorespecificar ações a serem executadas,e provê um conjunto de conceitospara o programador utilizar quando
está pensando sobre o que pode ser feito. O primeiro aspectoidealmente requer uma linguagem “próxima à máquina” (...) Osegundo aspecto idealmente requer uma linguagem que é “próximado problema a ser resolvido”, tal que os conceitos de uma soluçãopossam ser expressados de forma direta e concisa.
— Stroustrup, “The C++ Programming Language” (1985)
6 / 42
Abstrações e modelagemEspectro dos problemas
Martin Fowler, “Patterns of Enterprise Application Architecture” (2002)
O valor de um protótipo está no que ele te ensina, e nãono código em si. — Alan Cooper, “The Inmates Are Running the Asylum” (2004)
7 / 42
O que queremos de uma linguagem afinal?
No começo de um projeto...
Praticidade (multi-plataforma, linha de comando)Popularidade“Get the job done”
Mas eventualmente:
Eficiência, escalabilidadeModelagem do domínioAlta expressividade de maneira declarativaChecagens, testes, comprovação
8 / 42
Mas coisas novas são ruins!!
Python é confortavel, não tem um desempenho tão ruim,“tá funcionando”, porque eu usaria algo diferente?
Tirar a cabeça da solução e voltar para o problema.O domínio é o que importa.E tudo flui. Já pensou que o próprio Python édiferente do que já era?...
9 / 42
Desenvolvimento do Python
Python 0.9 (fev 1991) - estruturas dedados (list, dict, str, etc), funções,exceções, classes e módulos.Python 1.0 (jan 1994) - Python acquiredlambda, reduce, filter and map,courtesy of a Lisp hacker who missedthem and submitted working patches.Python 1.4 (oct 1996) - kwargs,complex numbers, name mangling
10 / 42
Desenvolvimento do Python
Python 2.0 (oct 2000) - comprehensionPython 2.2 (dez 2001) - iterators,simple generators (enumerate,xrange...), unificação de tipos e classesPython 2.4 (nov 2004) - generatorexpressions, decorators, set built-inPython 2.5 (set 2006) - conditionalexpressions, partially applied functionsPython 3.0 (dez 2008) - nerf reduceand print, function annotationsPython 2.7 (jul 2010) - set literals, dictcomprehensions
11 / 42
Desenvolvimento do Python
Estagnado. Muita gente agarrada no 2.7Várias coisas emprestadas de programação funcionalÓtimo para pesquisa, protótipo, projetos menores,mas corporativo?...
12 / 42
Scala
Scala busca o melhor dos dois mundos...
Criada por Martin Odersky em 2001 na EPFLLinguagem “séria”, mas modernaRoda na JVM, compatível com JavaFuncional, mas procedural se você quiserCompilada, mas tem um REPLTipagem estática, mas com inferência de tipoPopularidade crescente: LinkedIn, FourSquare,Netflix, Walmart, The Guardian, Twitter (ex-Ruby)
13 / 42
Scala
Scala busca o melhor dos dois mundos...
Criada por Martin Odersky em 2001 na EPFLLinguagem “séria”, mas modernaRoda na JVM, compatível com JavaFuncional, mas procedural se você quiserCompilada, mas tem um REPLTipagem estática, mas com inferência de tipoPopularidade crescente: LinkedIn, FourSquare,Netflix, Walmart, The Guardian, Twitter (ex-Ruby)
13 / 42
Scala
Scala busca o melhor dos dois mundos...
Criada por Martin Odersky em 2001 na EPFLLinguagem “séria”, mas modernaRoda na JVM, compatível com JavaFuncional, mas procedural se você quiserCompilada, mas tem um REPLTipagem estática, mas com inferência de tipoPopularidade crescente: LinkedIn, FourSquare,Netflix, Walmart, The Guardian, Twitter (ex-Ruby)
13 / 42
Scala
Scala busca o melhor dos dois mundos...
Criada por Martin Odersky em 2001 na EPFLLinguagem “séria”, mas modernaRoda na JVM, compatível com JavaFuncional, mas procedural se você quiserCompilada, mas tem um REPLTipagem estática, mas com inferência de tipoPopularidade crescente: LinkedIn, FourSquare,Netflix, Walmart, The Guardian, Twitter (ex-Ruby)
13 / 42
Scala
Scala busca o melhor dos dois mundos...
Criada por Martin Odersky em 2001 na EPFLLinguagem “séria”, mas modernaRoda na JVM, compatível com JavaFuncional, mas procedural se você quiserCompilada, mas tem um REPLTipagem estática, mas com inferência de tipoPopularidade crescente: LinkedIn, FourSquare,Netflix, Walmart, The Guardian, Twitter (ex-Ruby)
13 / 42
Scala
Scala busca o melhor dos dois mundos...
Criada por Martin Odersky em 2001 na EPFLLinguagem “séria”, mas modernaRoda na JVM, compatível com JavaFuncional, mas procedural se você quiserCompilada, mas tem um REPLTipagem estática, mas com inferência de tipoPopularidade crescente: LinkedIn, FourSquare,Netflix, Walmart, The Guardian, Twitter (ex-Ruby)
13 / 42
Scala
Scala busca o melhor dos dois mundos...
Criada por Martin Odersky em 2001 na EPFLLinguagem “séria”, mas modernaRoda na JVM, compatível com JavaFuncional, mas procedural se você quiserCompilada, mas tem um REPLTipagem estática, mas com inferência de tipoPopularidade crescente: LinkedIn, FourSquare,Netflix, Walmart, The Guardian, Twitter (ex-Ruby)
13 / 42
Comparando linguagens
(Super-simplificando, tá gente?)C++ Python Scala
Compilado ◦ × ◦Checagem de tipo ◦ × ◦Polimorfismo ◦ × ◦Interpretador × ◦ ◦Estruturas de dados nativas × ◦ ◦Geradores (nativo) × ◦ ◦Inferência de tipos × × ◦Tipos de dados algébricos × × ◦Pattern matching × × ◦Mônadas e monoides!!?!@ × × ◦
14 / 42
Finalmente, Scala“Hello World!” interativo
Welcome to Scala version 2.11.6 (OpenJDK 64-BitServer VM, Java 1.7.0_25).
Type in expressions to have them evaluated.Type :help for more information.
scala> println("Hello World!")Hello World!
scala>
15 / 42
Finalmente, Scala“Hello World!” com classe, e além
class HelloWorldMain {def main(args: Array[String]) = {
println("Hello, " + args(0) + "!");}
}
object HelloWorld extends App {println(s"Hello, ${args(0)}!")
}
~/scalaclass> scalac HelloWorld.scala~/scalaclass> scala HelloWorld geekiesHello, geekies!~/scalaclass>
16 / 42
Valores e variáveisscala> val w = 2w: Int = 2scala> w = 3<console>:8: error: reassignment to val
w = 3^
scala> var x = 3x: Int = 3scala> x = x + wx: Int = 5scala> val y: String = "a"y: String = ascala> val z: String = 1<console>:7: error: type mismatch;found : Int(1)required: String
val z: String = 1
17 / 42
Estruturas de dados básicas
Scala oferece excelentes implementações das estruturasde dados mais comuns.
Prefira tipos imutáveis. Se precisar de mutável, importscala.collection.mutable.Map
List é uma lista ligada. Há outros tipos do trait Seq,e.g. Array, Queue. Também é possível utilizar tiposnativos de Java.
18 / 42
Estruturas de dados básicas
19 / 42
scala> val q = List(1, 2, 3)q: List[Int] = List(1, 2, 3)scala> val w = 4 :: 5 :: 6 :: Nilw: List[Int] = List(4, 5, 6)scala> 7 :: wres0: List[Int] = List(7, 4, 5, 6)scala> q :: wres1: List[Any] = List(List(1, 2, 3), 4, 5, 6)scala> q ::: wres2: List[Int] = List(1, 2, 3, 4, 5, 6)scala> q ++ wres3: List[Int] = List(1, 2, 3, 4, 5, 6)scala> q :+ 4res4: List[Int] = List(1, 2, 3, 4)scala> q.headres5: Int = 1scala> w.tailres6: List[Int] = List(5, 6)
20 / 42
scala> (3, 4.0, "asd")res0: (Int, Double, String) = (3,4.0,asd)scala> res0._1res1: Int = 3scala> 1 -> 2res2: (Int, Int) = (1,2)scala> val q = Map("asd" -> 3, "zxc" -> 42)q: Map[String,Int] = Map(asd -> 3, zxc -> 42)scala> q - "asd"res3: Map[String,Int] = Map(zxc -> 42)scala> q + ("qwe" -> 54)res4: Map[String,Int] = Map(asd -> 3, zxc -> 42, qwe -> 54)scala> q ++ Map("asd" -> 9, "iop" -> 10)res5: Map[String,Int] = Map(asd -> 9, zxc -> 42, iop -> 10)scala> q("zxc")res6: Int = 42scala> q.get("bnm")res7: Option[Int] = Nonescala> q(33)<console>:9: error: type mismatch;found : Int(33)required: String
21 / 42
Funçõesscala> def f(x: Int): Int = x * xf: (x: Int)Intscala> f(2)res0: Int = 4scala> def myarg = {println("arg"); 42}myarg: Intscala> def eagerEval(x: Int) = {println("pressa"); x + x}eagerEval: (x: Int)Intscala> def lazyEval(x: => Int) = {println("pregui"); x + x}lazyEval: (x: => Int)Intscala> eagerEval(myarg)argpressares1: Int = 84scala> lazyEval(myarg)preguiargargres2: Int = 84
22 / 42
“Operadores”
scala> 3 + 4res0: Int = 7scala> 3.+(4)res1: Int = 7scala> 3.to(10)res2: Range.Inclusive = Range(3, 4, 5, 6, 7, 8, 9, 10)scala> 3 to 10res3: Range.Inclusive = Range(3, 4, 5, 6, 7, 8, 9, 10)
scala> 1 :: 2 :: 3 :: Nilres4: List[Int] = List(1, 2, 3)scala> ((Nil.::(3)).::(2)).::(1)res5: List[Int] = List(1, 2, 3)
23 / 42
Classes
class Biscoito(val x: Int, y: Int) {val z = x + ydef w = z + ydef f(a: Int) = x + adef apply(b: Int) = b + w - 10override def toString = s"abc$q"
}
24 / 42
Classesscala> val q = new Biscoito(5, 7)q: Biscoito = abc19scala> q.xres0: Int = 5scala> q.y<console>:10: error: value y is not a member of Biscoito
q.y^
scala> q.zres2: Int = 12scala> q.wres3: Int = 19scala> q.f(10)res4: Int = 15scala> q(100)res5: Int = 109scala> println(q)abc19
25 / 42
Condicionalscala> if (true) 5 else 2res32: Int = 5scala> if (5 > 0) "oi" else 321res33: Any = oiscala> val x = 1x: Int = 1scala> println(if (x > 2) "a" else if (x > 0) "b" else "c")b
if (x < 2) {println("foo")val n = 10f"bbb $n, $x%0df"
} else {println("bar")val n = 23s"ccc ${n+2}"
}26 / 42
Iteraçãoscala> var i = 0i: Int = 0scala> while (i < 10) {print(i); i += 1}0123456789scala> val aaa = List(0, 1, 2)aaa: List[Int] = List(0, 1, 2)scala> val bbb = List(3, 4, 5)bbb: List[Int] = List(3, 4, 5)scala> for (i <- aaa) print(i)012scala> for (i <- aaa) for (j <- aaa) print(i+j)012123234scala> for {i <- aaa
| j <- bbb}| {| val q = i+j| print(s"$i $j $q, ")| }
0 3 3, 0 4 4, 0 5 5, 1 3 4, 1 4 5, 1 5 6, 2 3 5, 2 4 6, 2 5 7,27 / 42
Compreensão de lista (for-expression)Ninguém faz nada disso!...
Quer imprimir um monte de valor? Usa foreach.
Quer gerar uma lista? Usa um for-expression.scala> for {
| i <- aaa| j <- bbb| q = i+j| if q != 5| } yield {| val w = q * q + 2| (q, w, q + w)| }
res3: List[(Int, Int, Int)] = List((3,11,14), (4,18,22),(4,18,22), (6,38,44), (6,38,44), (7,51,58))
28 / 42
Pirações funcionais
scala> val q = (0 to 5).toListq: List[Int] = List(0, 1, 2, 3, 4, 5)scala> q.map(_ + 2)res0: List[Int] = List(2, 3, 4, 5, 6, 7)scala> q.filter(3 > _)res1: List[Int] = List(0, 1, 2)scala> q.reduce(_ - _)res2: Int = -15scala> q.reduce((a, b) => (b * 10) / (a + 1))res3: Int = 16scala> q reduce {(a, b) => (b * 10) / (a + 1)}res4: Int = 16scala> q.foldLeft("")((a, b) => a + b.toString)res5: String = 012345scala> ("" /: q) {(a, b) => a + b.toString}res6: String = 012345
29 / 42
Tipos de dados algébricos
sealed trait Lancecase object Errou extends Lancecase object Aro extends Lancecase class Cesta(pontos: Int) extends Lance
sealed trait List[+A]case object Nil extends List[Nothing]case class Cons[+A](head: A, tail: List[A]) extends List[A]
sealed trait Tree[+A]case class Leaf[A](value: A) extends Tree[A]case class Branch[A](left: Tree[A], right: Tree[A]) extends
Tree[A]
30 / 42
Pattern matching(1 until 100).map(i => (i % 3, i % 5) match {
case (0, 0) => "FizzBuzz"case (0, _) => "Fizz"case (_, 0) => "Buzz"case _ => i
}).foreach(println)
scala> def fb(i: Int) = (i % 3 == 0, i % 5 == 0) match {| case (true, true) => "FizzBuzz"| case (false, true) => "Fizz"| case (true, false) => "Buzz"| }
<console>:7: warning: match may not be exhaustive.It would fail on the following input: (false, false)
def fb(i: Int) = (i % 3 == 0, i % 5 == 0) match {^
fb: (i: Int)String
31 / 42
Pattern matching
def mensagem(lance: Lance) =lance match {
case Errou => "Errou feio"case Aro => "Quaaaaase!!"case Cesta(p) => s"Parabens, ganhou $p pontos!"
}
scala> List(Aro, Errou, Cesta(3)) map mensagem foreach printlnQuaaaaase!!Errou feioParabens, ganhou 3 pontos!
32 / 42
Pattern matching
def map[A, B](l: List[A])(f: A => B): List[B] =l match {
case Nil => Nilcase Cons(x, xs) => Cons(f(x), map(xs)(f))
}def foldLeft[A,B](l: List[A], z: B)(f: (A, B) => B): B =
l match {case Nil => zcase Cons(x, xs) => foldLeft(xs, f(x, z))(f)
}def length[A](l: List[A]): Int =
foldLeft(l, 0)((i, c) => c + 1)
33 / 42
Pattern matching
def size(t: Tree[Int]): Int = {@tailrecdef inner_size(l: List[Tree[Int]], acc: Int): Int =
l match {case Nil => acccase Leaf(v) :: ls => inner_size(ls, acc + 1)case Branch(a, b) :: ls => inner_size(a :: b :: ls, acc
+ 1)}
inner_size(List(t), 0)}
34 / 42
A classe Option
Maneira funcional e maravilhosa de lidar com falhas!scala> def div(a: Int, b: Int) = b match {
| case 0 => None| case _ => Some(a / b)| }
div: (a: Int, b: Int)Option[Int]
scala> val q = List(div(11, 3), div(15, 0), div(2, -11))q: List[Option[Int]] = List(Some(3), None, Some(0))
scala> q.foreach(_ match {| case Some(x) => println(s"Deu $x.")| case None => println("Deu pau.")| })
Deu 3.Deu pau.Deu 0.
35 / 42
A classe Option
scala> Some(2).map(_ + 2)res1: Option[Int] = Some(4)
scala> (None: Option[Int]).map(_ + 2)res2: Option[Int] = None
scala> def divp = (div _).tupleddivp: ((Int, Int)) => Option[Int]
scala> Some((43, 9)).map(divp)res3: Option[Option[Int]] = Some(Some(4))
scala> Some((43, 9)).flatMap(divp)res4: Option[Int] = Some(4)
scala> None.flatMap(divp)res5: Option[Int] = None
36 / 42
MônadasO que são mônadas?
Mônadas são simplesmente monoides na categoria dosendo-funtores.
37 / 42
MônadasO que são mônadas?
Mônadas são simplesmente monoides na categoria dosendo-funtores.
37 / 42
MônadasO que são mônadas?
Mônadas são simplesmente monoides na categoria dosendo-funtores.
37 / 42
Mônadas
Mônadas são um design pattern que surge naturalmente,muito útil em programação funcional.
Elas implementam diferentes funcionalidades, estendendooutros tipos.
Solução meio óbvia pra alguns problemas... Mas o fatode ser um padrão não é tão óbvio.
Exemplos: Option monad, list monad, writer monad,state monad...
38 / 42
Mônadas
Mônadas são classes com um par de métodos
unit: A => M[A]bind: (M[A], A => M[A]) => M[A]
E que ainda devem obedecer certas restrições...
39 / 42
MônadasWriter monad — exemplo em Python
def verbose_u(x):return (x + 4, [’verbose_u com x=’ + str(x)])
def verbose_v(x):return (x * 2, [’verbose_v com x=’ + str(x)])
def unit(x):return (x, [’criado’])
def bind(x, f):input, log = xresult, msg = f(input)return (result, log + msg)
>>> bind(bind(unit(4), verbose_v), verbose_u)(12, [’criado’, ’verbose_v com x=4’, ’verbose_u com x=8’])
40 / 42
Monoides
Em álgebra abstrata, um monoide é uma estruturaalgébrica com uma única operação binária, associativa, ecom um elemento neutro.
Exemplos:
Os números inteiros, a + e o 0Os números inteiros, a × e o 1
Características interessantes para a computação, e.g.reduce paralelizável.
41 / 42
Conclusão
Scala is hot, Python is not, and
Obrigado!!
42 / 42
Referências Bibliográficas
Martin Odersky, Lex Spoon e Bill Venners,“Programming in Scala” (2010)Paul Chiusado e Rúnar Bjarnson, “FunctionalProgramming in Scala” (2013)Stephan Boyer, “Monads, Part 1: A DesignPattern”. http://www.stephanboyer.com/post/9/monads-part-1-a-design-pattern
1 / 1