O documento discute a linguagem de programação Scala, comparando-a a outras linguagens como C++, Python e Java. Scala oferece características funcionais e procedurais, tipagem estática com inferência de tipo, e roda na máquina virtual Java. O documento apresenta exemplos básicos em Scala e discute as vantagens dessa linguagem multi-paradigma.
2. Roteiro
A vida, o universo e tudo mais
Porque Scala?
Aula de Scala
1 / 42
3. O Programador Humilde
Minha primeira observação é que,
apesar da atividade do programador
terminar quando ele constrói um
programa correto, é o processo que
ocorre sob o controle do programa que
é o verdadeiro tema de seu trabalho,
porque é este processo que produz os
efeitos desejados, é este processo que
em seu comportamento dinâmico deve
satisfazer as especificações desejadas.
Ainda assim, uma vez que o programa foi feito, a condução do
processo correspondente é delegado à máquina.
2 / 42
4. O Programador Humilde
Minha segunda observação e que nossos poderes intelectuais
são voltados para dominar relações estáticas, e nossos poderes de
visualizar processos evoluindo no tempo
são relativamente mal-desenvolvidos. Por
isto devemos, como sábios programadores
cientes de nossas limitações, fazer nosso
absoluto melhor para reduzir a separação
conceitual entre o programa estático e o
processo dinâmico, para tornar tão trivial
quanto possível a correspondência entre
o programa, espalhado no espaço dos
textos, e o processo, espalhado no tempo.
— EWD215 “A case against the go-to statement”, Comm. ACM 11 (1968)
3 / 42
5. O Programador Humilde
Nós devemos fazer um trabalho
bem melhor de programação, desde que
saibamos: abordar a tarefa com uma completa
apreciação de sua tremenda dificuldade;
nos ater a linguagens de programação
modestas e elegantes; respeitar os limites
intrínsecos da mente humana, e abordar a
tarefa como um Programador Muito Humilde.
— Dijkstra, EWD340 “The Humble Programmer” (1972)
4 / 42
6. O Programador Humilde
Nós devemos fazer um trabalho
bem melhor de programação, desde que
saibamos: abordar a tarefa com uma completa
apreciação de sua tremenda dificuldade;
nos ater a linguagens de programação
modestas e elegantes; respeitar os limites
intrínsecos da mente humana, e abordar a
tarefa como um Programador Muito Humilde.
— Dijkstra, EWD340 “The Humble Programmer” (1972)
4 / 42
7. O Programador Humilde
Humilde mas ambicioso...
Programas devem ser compostos corretamente, e não
apenas depurados até a correção.
Benefícios da humildade em desenvolvimento de software:
Lidar com suas limitações cognitivas como
programador
Aprender novas técnicas
Testar novas ferramentas
Aprender o que o usuário precisa (modelagem)
Descobrir o que ninguém nem desconfiava
5 / 42
8. O Programador Humilde
Humilde mas ambicioso...
Programas devem ser compostos corretamente, e não
apenas depurados até a correção.
Benefícios da humildade em desenvolvimento de software:
Lidar com suas limitações cognitivas como
programador
Aprender novas técnicas
Testar novas ferramentas
Aprender o que o usuário precisa (modelagem)
Descobrir o que ninguém nem desconfiava
5 / 42
9. O Programador Humilde
Humilde mas ambicioso...
Programas devem ser compostos corretamente, e não
apenas depurados até a correção.
Benefícios da humildade em desenvolvimento de software:
Lidar com suas limitações cognitivas como
programador
Aprender novas técnicas
Testar novas ferramentas
Aprender o que o usuário precisa (modelagem)
Descobrir o que ninguém nem desconfiava
5 / 42
10. O Programador Humilde
Humilde mas ambicioso...
Programas devem ser compostos corretamente, e não
apenas depurados até a correção.
Benefícios da humildade em desenvolvimento de software:
Lidar com suas limitações cognitivas como
programador
Aprender novas técnicas
Testar novas ferramentas
Aprender o que o usuário precisa (modelagem)
Descobrir o que ninguém nem desconfiava
5 / 42
11. O Programador Humilde
Humilde mas ambicioso...
Programas devem ser compostos corretamente, e não
apenas depurados até a correção.
Benefícios da humildade em desenvolvimento de software:
Lidar com suas limitações cognitivas como
programador
Aprender novas técnicas
Testar novas ferramentas
Aprender o que o usuário precisa (modelagem)
Descobrir o que ninguém nem desconfiava
5 / 42
12. O Programador Humilde
Humilde mas ambicioso...
Programas devem ser compostos corretamente, e não
apenas depurados até a correção.
Benefícios da humildade em desenvolvimento de software:
Lidar com suas limitações cognitivas como
programador
Aprender novas técnicas
Testar novas ferramentas
Aprender o que o usuário precisa (modelagem)
Descobrir o que ninguém nem desconfiava
5 / 42
13. O Programador Humilde
Humilde mas ambicioso...
Programas devem ser compostos corretamente, e não
apenas depurados até a correção.
Benefícios da humildade em desenvolvimento de software:
Lidar com suas limitações cognitivas como
programador
Aprender novas técnicas
Testar novas ferramentas
Aprender o que o usuário precisa (modelagem)
Descobrir o que ninguém nem desconfiava
5 / 42
14. O Programador Humilde
Humilde mas ambicioso...
Programas devem ser compostos corretamente, e não
apenas depurados até a correção.
Benefícios da humildade em desenvolvimento de software:
Lidar com suas limitações cognitivas como
programador
Aprender novas técnicas
Testar novas ferramentas
Aprender o que o usuário precisa (modelagem)
Descobrir o que ninguém nem desconfiava
5 / 42
15. Abstrações e modelagem
Uma linguagem de programação serve
a dois propósitos relacionados: ela
provê um veículo para o programador
especificar ações a serem executadas,
e provê um conjunto de conceitos
para o programador utilizar quando
está pensando sobre o que pode ser feito. O primeiro aspecto
idealmente requer uma linguagem “próxima à máquina” (...) O
segundo aspecto idealmente requer uma linguagem que é “próxima
do problema a ser resolvido”, tal que os conceitos de uma solução
possam ser expressados de forma direta e concisa.
— Stroustrup, “The C++ Programming Language” (1985)
6 / 42
16. Abstrações e modelagem
Espectro dos problemas
Martin Fowler, “Patterns of Enterprise Application Architecture” (2002)
O valor de um protótipo está no que ele te ensina, e não
no código em si. — Alan Cooper, “The Inmates Are Running the Asylum” (2004)
7 / 42
17. 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, escalabilidade
Modelagem do domínio
Alta expressividade de maneira declarativa
Checagens, testes, comprovação
8 / 42
18. 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
19. Desenvolvimento do Python
Python 0.9 (fev 1991) - estruturas de
dados (list, dict, str, etc), funções,
exceções, classes e módulos.
Python 1.0 (jan 1994) - Python acquired
lambda, reduce, filter and map,
courtesy of a Lisp hacker who missed
them and submitted working patches.
Python 1.4 (oct 1996) - kwargs,
complex numbers, name mangling
10 / 42
20. Desenvolvimento do Python
Python 2.0 (oct 2000) - comprehension
Python 2.2 (dez 2001) - iterators,
simple generators (enumerate,
xrange...), unificação de tipos e classes
Python 2.4 (nov 2004) - generator
expressions, decorators, set built-in
Python 2.5 (set 2006) - conditional
expressions, partially applied functions
Python 3.0 (dez 2008) - nerf reduce
and print, function annotations
Python 2.7 (jul 2010) - set literals, dict
comprehensions
11 / 42
21. Desenvolvimento do Python
Estagnado. Muita gente agarrada no 2.7
Várias coisas emprestadas de programação funcional
Ótimo para pesquisa, protótipo, projetos menores,
mas corporativo?...
12 / 42
22. Scala
Scala busca o melhor dos dois mundos...
Criada por Martin Odersky em 2001 na EPFL
Linguagem “séria”, mas moderna
Roda na JVM, compatível com Java
Funcional, mas procedural se você quiser
Compilada, mas tem um REPL
Tipagem estática, mas com inferência de tipo
Popularidade crescente: LinkedIn, FourSquare,
Netflix, Walmart, The Guardian, Twitter (ex-Ruby)
13 / 42
23. Scala
Scala busca o melhor dos dois mundos...
Criada por Martin Odersky em 2001 na EPFL
Linguagem “séria”, mas moderna
Roda na JVM, compatível com Java
Funcional, mas procedural se você quiser
Compilada, mas tem um REPL
Tipagem estática, mas com inferência de tipo
Popularidade crescente: LinkedIn, FourSquare,
Netflix, Walmart, The Guardian, Twitter (ex-Ruby)
13 / 42
24. Scala
Scala busca o melhor dos dois mundos...
Criada por Martin Odersky em 2001 na EPFL
Linguagem “séria”, mas moderna
Roda na JVM, compatível com Java
Funcional, mas procedural se você quiser
Compilada, mas tem um REPL
Tipagem estática, mas com inferência de tipo
Popularidade crescente: LinkedIn, FourSquare,
Netflix, Walmart, The Guardian, Twitter (ex-Ruby)
13 / 42
25. Scala
Scala busca o melhor dos dois mundos...
Criada por Martin Odersky em 2001 na EPFL
Linguagem “séria”, mas moderna
Roda na JVM, compatível com Java
Funcional, mas procedural se você quiser
Compilada, mas tem um REPL
Tipagem estática, mas com inferência de tipo
Popularidade crescente: LinkedIn, FourSquare,
Netflix, Walmart, The Guardian, Twitter (ex-Ruby)
13 / 42
26. Scala
Scala busca o melhor dos dois mundos...
Criada por Martin Odersky em 2001 na EPFL
Linguagem “séria”, mas moderna
Roda na JVM, compatível com Java
Funcional, mas procedural se você quiser
Compilada, mas tem um REPL
Tipagem estática, mas com inferência de tipo
Popularidade crescente: LinkedIn, FourSquare,
Netflix, Walmart, The Guardian, Twitter (ex-Ruby)
13 / 42
27. Scala
Scala busca o melhor dos dois mundos...
Criada por Martin Odersky em 2001 na EPFL
Linguagem “séria”, mas moderna
Roda na JVM, compatível com Java
Funcional, mas procedural se você quiser
Compilada, mas tem um REPL
Tipagem estática, mas com inferência de tipo
Popularidade crescente: LinkedIn, FourSquare,
Netflix, Walmart, The Guardian, Twitter (ex-Ruby)
13 / 42
28. Scala
Scala busca o melhor dos dois mundos...
Criada por Martin Odersky em 2001 na EPFL
Linguagem “séria”, mas moderna
Roda na JVM, compatível com Java
Funcional, mas procedural se você quiser
Compilada, mas tem um REPL
Tipagem estática, mas com inferência de tipo
Popularidade crescente: LinkedIn, FourSquare,
Netflix, Walmart, The Guardian, Twitter (ex-Ruby)
13 / 42
29. 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
30. Finalmente, Scala
“Hello World!” interativo
Welcome to Scala version 2.11.6 (OpenJDK 64-Bit
Server 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
32. Valores e variáveis
scala> val w = 2
w: Int = 2
scala> w = 3
<console>:8: error: reassignment to val
w = 3
^
scala> var x = 3
x: Int = 3
scala> x = x + w
x: Int = 5
scala> val y: String = "a"
y: String = a
scala> val z: String = 1
<console>:7: error: type mismatch;
found : Int(1)
required: String
val z: String = 1
17 / 42
33. Estruturas de dados básicas
Scala oferece excelentes implementações das estruturas
de dados mais comuns.
Prefira tipos imutáveis. Se precisar de mutável, import
scala.collection.mutable.Map
List é uma lista ligada. Há outros tipos do trait Seq,
e.g. Array, Queue. Também é possível utilizar tipos
nativos de Java.
18 / 42
39. Classes
class Biscoito(val x: Int, y: Int) {
val z = x + y
def w = z + y
def f(a: Int) = x + a
def apply(b: Int) = b + w - 10
override def toString = s"abc$q"
}
24 / 42
40. Classes
scala> val q = new Biscoito(5, 7)
q: Biscoito = abc19
scala> q.x
res0: Int = 5
scala> q.y
<console>:10: error: value y is not a member of Biscoito
q.y
^
scala> q.z
res2: Int = 12
scala> q.w
res3: Int = 19
scala> q.f(10)
res4: Int = 15
scala> q(100)
res5: Int = 109
scala> println(q)
abc19
25 / 42
41. Condicional
scala> if (true) 5 else 2
res32: Int = 5
scala> if (5 > 0) "oi" else 321
res33: Any = oi
scala> val x = 1
x: Int = 1
scala> println(if (x > 2) "a" else if (x > 0) "b" else "c")
b
if (x < 2) {
println("foo")
val n = 10
f"bbb $n, $x%0df"
} else {
println("bar")
val n = 23
s"ccc ${n+2}"
}
26 / 42
42. Iteração
scala> var i = 0
i: Int = 0
scala> while (i < 10) {print(i); i += 1}
0123456789
scala> 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)
012
scala> for (i <- aaa) for (j <- aaa) print(i+j)
012123234
scala> 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
43. 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
44. Pirações funcionais
scala> val q = (0 to 5).toList
q: 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 = -15
scala> q.reduce((a, b) => (b * 10) / (a + 1))
res3: Int = 16
scala> q reduce {(a, b) => (b * 10) / (a + 1)}
res4: Int = 16
scala> q.foldLeft("")((a, b) => a + b.toString)
res5: String = 012345
scala> ("" /: q) {(a, b) => a + b.toString}
res6: String = 012345
29 / 42
45. Tipos de dados algébricos
sealed trait Lance
case object Errou extends Lance
case object Aro extends Lance
case 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
46. 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
47. 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 println
Quaaaaase!!
Errou feio
Parabens, ganhou 3 pontos!
32 / 42
48. Pattern matching
def map[A, B](l: List[A])(f: A => B): List[B] =
l match {
case Nil => Nil
case 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 => z
case 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
49. Pattern matching
def size(t: Tree[Int]): Int = {
@tailrec
def inner_size(l: List[Tree[Int]], acc: Int): Int =
l match {
case Nil => acc
case 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
50. 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
52. Mônadas
O que são mônadas?
Mônadas são simplesmente monoides na categoria dos
endo-funtores.
37 / 42
53. Mônadas
O que são mônadas?
Mônadas são simplesmente monoides na categoria dos
endo-funtores.
37 / 42
54. Mônadas
O que são mônadas?
Mônadas são simplesmente monoides na categoria dos
endo-funtores.
37 / 42
55. Mônadas
Mônadas são um design pattern que surge naturalmente,
muito útil em programação funcional.
Elas implementam diferentes funcionalidades, estendendo
outros tipos.
Solução meio óbvia pra alguns problemas... Mas o fato
de ser um padrão não é tão óbvio.
Exemplos: Option monad, list monad, writer monad,
state monad...
38 / 42
56. 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
58. Monoides
Em álgebra abstrata, um monoide é uma estrutura
algébrica com uma única operação binária, associativa, e
com um elemento neutro.
Exemplos:
Os números inteiros, a + e o 0
Os números inteiros, a × e o 1
Características interessantes para a computação, e.g.
reduce paralelizável.
41 / 42
60. Referências Bibliográficas
Martin Odersky, Lex Spoon e Bill Venners,
“Programming in Scala” (2010)
Paul Chiusado e Rúnar Bjarnson, “Functional
Programming in Scala” (2013)
Stephan Boyer, “Monads, Part 1: A Design
Pattern”. http://www.stephanboyer.com/post/
9/monads-part-1-a-design-pattern
1 / 1