Scala
Unindo programação funcional
e orientação a objetos
Felipe Hummel
Quem?
• Graduação (2008) e Mestrado (2011) pela UFAM
• NewsMonitor
• Desde 2012, morando em São Paulo nos últimos 2 anos
• Site profissional para monitoramento de notícias em tempo real
• 170M de notícias
• 5M/mês
• ~30K linhas de código Scala (2 Devs back-end)
• Maiores desafios estão na coleta, processamento e busca de notícias
Scala, o quê?
• Relativamente “nova" (2004) começando a ganhar tração
depois de 2010
• Linguagem com tipagem forte e estática (“mais" do que
outras)
• “Multiparadigma”: funcional + OO
• Open Source
• Compila para bytecode da JVM (Java Virtual Machine)
• Facilmente interoperável com código e libs Java
Scala, quem usa?
Scala, quem usa?
Scala, por quê?
• Consegue ser roazavelmente familiar mas ainda introduz conceitos
funcionais que mudam a forma como programamos
• Concisão de código sem perca de legibilidade
• Inferência de tipos (local, diferente de Haskell/ML)
• Coleções muito ricas em funcionalidades
• 90% da rotina é lidar com coleções de objetos
• Preferência por imutabilidade
• Quase tudo faz parte da biblioteca e não é sintaxe especial da linguagem
• Poder para expressar muita coisa
Scala
sudo apt-get install scala
Val e Var
val soma = 1 + 1

Val e Var
val soma = 1 + 1

soma = 10 //error: reassignment to val
Val e Var
var soma = 1 + 1

Val e Var
var soma = 1 + 1

soma = soma + 1 //OK!
Inferência de tipos
val soma = 1 + 1

Inferência de tipos


val soma: Int = 1 + 1

soma.substring(0)

//error: value substring is not a member of Int
Inferência de tipos


val soma = 1 + 1

soma.substring(0)

//error: value substring is not a member of Int
Inferência de tipos
val soma: Int = 1 + 1

val nome: String = “teste"

val lista: List[String] = List(“teste”)

Inferência de tipos
val soma = 1 + 1

val nome = “teste"

val lista = List(“teste”)

Funções


def add1(n: Int) = n + 1

// ^ inferência de tipo de retorno
Funções


def add1(n: Int): Int = n + 1

// ^ tipo de retorno explícito
Funções


def add1(n: Int): Int = { 

println(“adicionando 1”)

n + 1 // última expressão: retorno automático

}

Funções anônimas


val f = (n: Int) => n + 1 

// ^ inferindo tipo de retorno

f(1) // retorna 2





val g: (Int => Int) = n => n * 2

val h: (Int => Int) = _ * 2

Funções anônimas


val f = (n: Int) => n + 1 

val g: (Int => Int) = n => n * 2



val fg = f.andThen(g) 

fg(10) // retorna 22

Lazy vals
lazy val usuários = todosUsuarios()

// todosUsuarios() ainda não foi chamada!!



val result = usuarios

// todosUsuarios() foi chamada agora



println(usuarios)// não precisou recomputar
Classes
class Curso(id: Int, nome: String)

class Aluno(id: Int, curso: Curso, idade: Int)
Classes
// ISSO NÃO É SCALA CORRETO! 

class Curso {

private val id: Int

private val nome: String

def constructor(_id: Int, _nome: String) {

id = _id

nome = _nome

}

}
Classes
// ISSO É SCALA CORRETO! 

class Curso(id: Int, nome: String)









Classes




class Curso(id: Int, nome: String)



val computacao = new Curso(1,“Computação”)



println(computacao.nome) 

//error: value nome is not a member of Curso

// nome não é acessível publicamente
Classes




class Curso(val id: Int, val nome: String)



val computacao = new Curso(1,“Computação”)



println(computacao.nome) 

// Computação

Classes




class Curso(id: Int, nome: String) {

def comoString(): String =

s”Curso($id, $nome)“

}



val computacao = new Curso(1,“Computação”)



println(computacao.comoString()) 

// Curso(1, Computação)
case classes










case class Curso(id: Int, nome: String)



val computacao = Curso(1,“Computação”)



println(computacao) 

// Curso(1, Computação)
case classes


// implementa pra mim:

// - toString() bonitinho

// - equals() e hashCode()

// - atributos são públicos e imutáveis por padrão

// - não precisa do new para instanciar objeto

case class Curso(id: Int, nome: String)



val computacao = Curso(1,“Computação”)



println(computacao) 

// Curso(1, Computação)
public class Person {

private final String firstName;

private final String lastName;
String getFirstName() { return firstName; }

String getLastName() { return lastName; }



public Person(String first, String last) {

this.firstName = first;

this.lastName = last;

}



public int hashCode() {

return goodHashCode(firstName, lastName);

}

public boolean equals(Object o) {

if ( this == aThat ) return true;

if ( !(aThat instanceof Person) ) return false;

Person that = (Person)aThat;

return EqualsUtil.areEqual(this.firstName, that.firstName) &

EqualsUtil.areEqual(this.lastName, that.lastName);

}

}
case class Person(firstName: String, lastName: String)
objects
// um "singleton"

object ContadorGlobal {

var contador = 0

def incrementaERetorna() = {

contador += 1

contador

}

}

// apesar do exemplo, por favor não criem vars globais :)

ContadorGlobal.incrementaERetorna() // 1

ContadorGlobal.incrementaERetorna() // 2

ContadorGlobal.incrementaERetorna() // 3



parâmetros de tipo
(generics)
val cursos: List[String] =

List(“Computação”, “Matemática”, "Física")





val cursosPorNome: Map[String, Int] =

Map("Computação" -> 1234,

"Matemática" -> 423,

"Física" -> 5322,

"Biologia" -> 1312)

Coleções!
Mão na massa
Scala é isso
80% de Scala é isso
Scala
mudou a forma
como programamos
Parar de acessar
o que não está lá
• NullPointerException (Java)
• Segmentation Fault (C/C++)
• undefined is not a function (Javascript)
• AttributeError: 'NoneType' object has no
attribute (Python)
• Call to a member function on a non-object
(PHP)
Parar de acessar
o que não está lá
• NullPointerException (Java)
• undefined is not a function (Javascript)
• AttributeError: 'NoneType' object has no
attribute (Python)
• Call to a member function on a non-object
(PHP)
Null Pointer Exc… NÃO
• NullPointerException (Java)
• undefined is not a function (Javascript)
• AttributeError: 'NoneType' object has no
attribute (Python)
• Call to a member function on a non-object
(PHP)
SCALA
NÃO TEM
!!!!!!!!!
Null Pointer Exc… NÃO
• Uso de Option[MeuTipo] quando necessário
Tipagem Estática!
• Linguagens com tipagem estáticas pegaram fama de serem
verbosas
• Não necessariamente
• Scala consegue ser tão concisa quanto as linguagens dinâmicas
• Tendência de adicionar tipos opcionais nas linguagens
dinâmicas
• Javascript, PHP, Python
• Difícil viver sem um compilador me ajudando
Imutabilidade
• Coisas a menos pra guardar na sua cabeça
• Não me preocupo se alguém pode ou vai mudar
meu objeto
• Você pode passar objetos imutáveis pra lá e pra cá de
boa
• Thread-safe por padrão
Scala é a melhor coisa do
mundo?
Scala é a melhor coisa do
mundo?
A minha
linguagem/framework/biblioteca
não é a melhor possível
Mais conciso e expressivo
que Scala é impossível
Mais conciso e expressivo
que Haskell é impossível
Programação é sempre um
comando seguido do outro
Programação pode ser só
(funções (chamando (funções ‘!’)))
em Clojure
Ou damos free() na mão
ou usamos Garbage Collector
Ou damos free() na mão
ou usamos Garbage Collector
ou usamos Rust
e o seu sistema de ownership
Sempre dá pra melhorar
Obrigado!
Dúvidas?
@felipehummel
felipehummel@gmail.com

Scala: unindo programação funcional e orientação a objetos

  • 1.
    Scala Unindo programação funcional eorientação a objetos Felipe Hummel
  • 2.
    Quem? • Graduação (2008)e Mestrado (2011) pela UFAM • NewsMonitor • Desde 2012, morando em São Paulo nos últimos 2 anos • Site profissional para monitoramento de notícias em tempo real • 170M de notícias • 5M/mês • ~30K linhas de código Scala (2 Devs back-end) • Maiores desafios estão na coleta, processamento e busca de notícias
  • 3.
    Scala, o quê? •Relativamente “nova" (2004) começando a ganhar tração depois de 2010 • Linguagem com tipagem forte e estática (“mais" do que outras) • “Multiparadigma”: funcional + OO • Open Source • Compila para bytecode da JVM (Java Virtual Machine) • Facilmente interoperável com código e libs Java
  • 4.
  • 5.
  • 6.
    Scala, por quê? •Consegue ser roazavelmente familiar mas ainda introduz conceitos funcionais que mudam a forma como programamos • Concisão de código sem perca de legibilidade • Inferência de tipos (local, diferente de Haskell/ML) • Coleções muito ricas em funcionalidades • 90% da rotina é lidar com coleções de objetos • Preferência por imutabilidade • Quase tudo faz parte da biblioteca e não é sintaxe especial da linguagem • Poder para expressar muita coisa
  • 7.
  • 8.
  • 9.
    Val e Var valsoma = 1 + 1

  • 10.
    Val e Var valsoma = 1 + 1
 soma = 10 //error: reassignment to val
  • 11.
    Val e Var varsoma = 1 + 1

  • 12.
    Val e Var varsoma = 1 + 1
 soma = soma + 1 //OK!
  • 13.
    Inferência de tipos valsoma = 1 + 1

  • 14.
    Inferência de tipos 
 valsoma: Int = 1 + 1
 soma.substring(0)
 //error: value substring is not a member of Int
  • 15.
    Inferência de tipos 
 valsoma = 1 + 1
 soma.substring(0)
 //error: value substring is not a member of Int
  • 16.
    Inferência de tipos valsoma: Int = 1 + 1
 val nome: String = “teste"
 val lista: List[String] = List(“teste”)

  • 17.
    Inferência de tipos valsoma = 1 + 1
 val nome = “teste"
 val lista = List(“teste”)

  • 18.
    Funções 
 def add1(n: Int)= n + 1
 // ^ inferência de tipo de retorno
  • 19.
    Funções 
 def add1(n: Int):Int = n + 1
 // ^ tipo de retorno explícito
  • 20.
    Funções 
 def add1(n: Int):Int = { 
 println(“adicionando 1”)
 n + 1 // última expressão: retorno automático
 }

  • 21.
    Funções anônimas 
 val f= (n: Int) => n + 1 
 // ^ inferindo tipo de retorno
 f(1) // retorna 2
 
 
 val g: (Int => Int) = n => n * 2
 val h: (Int => Int) = _ * 2

  • 22.
    Funções anônimas 
 val f= (n: Int) => n + 1 
 val g: (Int => Int) = n => n * 2
 
 val fg = f.andThen(g) 
 fg(10) // retorna 22

  • 23.
    Lazy vals lazy valusuários = todosUsuarios()
 // todosUsuarios() ainda não foi chamada!!
 
 val result = usuarios
 // todosUsuarios() foi chamada agora
 
 println(usuarios)// não precisou recomputar
  • 24.
    Classes class Curso(id: Int,nome: String)
 class Aluno(id: Int, curso: Curso, idade: Int)
  • 25.
    Classes // ISSO NÃOÉ SCALA CORRETO! 
 class Curso {
 private val id: Int
 private val nome: String
 def constructor(_id: Int, _nome: String) {
 id = _id
 nome = _nome
 }
 }
  • 26.
    Classes // ISSO ÉSCALA CORRETO! 
 class Curso(id: Int, nome: String)
 
 
 
 

  • 27.
    Classes 
 
 class Curso(id: Int,nome: String)
 
 val computacao = new Curso(1,“Computação”)
 
 println(computacao.nome) 
 //error: value nome is not a member of Curso
 // nome não é acessível publicamente
  • 28.
    Classes 
 
 class Curso(val id:Int, val nome: String)
 
 val computacao = new Curso(1,“Computação”)
 
 println(computacao.nome) 
 // Computação

  • 29.
    Classes 
 
 class Curso(id: Int,nome: String) {
 def comoString(): String =
 s”Curso($id, $nome)“
 }
 
 val computacao = new Curso(1,“Computação”)
 
 println(computacao.comoString()) 
 // Curso(1, Computação)
  • 30.
    case classes 
 
 
 
 
 case classCurso(id: Int, nome: String)
 
 val computacao = Curso(1,“Computação”)
 
 println(computacao) 
 // Curso(1, Computação)
  • 31.
    case classes 
 // implementapra mim:
 // - toString() bonitinho
 // - equals() e hashCode()
 // - atributos são públicos e imutáveis por padrão
 // - não precisa do new para instanciar objeto
 case class Curso(id: Int, nome: String)
 
 val computacao = Curso(1,“Computação”)
 
 println(computacao) 
 // Curso(1, Computação)
  • 32.
    public class Person{
 private final String firstName;
 private final String lastName; String getFirstName() { return firstName; }
 String getLastName() { return lastName; }
 
 public Person(String first, String last) {
 this.firstName = first;
 this.lastName = last;
 }
 
 public int hashCode() {
 return goodHashCode(firstName, lastName);
 }
 public boolean equals(Object o) {
 if ( this == aThat ) return true;
 if ( !(aThat instanceof Person) ) return false;
 Person that = (Person)aThat;
 return EqualsUtil.areEqual(this.firstName, that.firstName) &
 EqualsUtil.areEqual(this.lastName, that.lastName);
 }
 }
  • 33.
    case class Person(firstName:String, lastName: String)
  • 34.
    objects // um "singleton"
 objectContadorGlobal {
 var contador = 0
 def incrementaERetorna() = {
 contador += 1
 contador
 }
 }
 // apesar do exemplo, por favor não criem vars globais :)
 ContadorGlobal.incrementaERetorna() // 1
 ContadorGlobal.incrementaERetorna() // 2
 ContadorGlobal.incrementaERetorna() // 3
 

  • 35.
    parâmetros de tipo (generics) valcursos: List[String] =
 List(“Computação”, “Matemática”, "Física")
 
 
 val cursosPorNome: Map[String, Int] =
 Map("Computação" -> 1234,
 "Matemática" -> 423,
 "Física" -> 5322,
 "Biologia" -> 1312)

  • 36.
  • 37.
  • 38.
  • 39.
    80% de Scalaé isso
  • 40.
  • 41.
    Parar de acessar oque não está lá • NullPointerException (Java) • Segmentation Fault (C/C++) • undefined is not a function (Javascript) • AttributeError: 'NoneType' object has no attribute (Python) • Call to a member function on a non-object (PHP)
  • 42.
    Parar de acessar oque não está lá • NullPointerException (Java) • undefined is not a function (Javascript) • AttributeError: 'NoneType' object has no attribute (Python) • Call to a member function on a non-object (PHP)
  • 43.
    Null Pointer Exc…NÃO • NullPointerException (Java) • undefined is not a function (Javascript) • AttributeError: 'NoneType' object has no attribute (Python) • Call to a member function on a non-object (PHP) SCALA NÃO TEM !!!!!!!!!
  • 44.
    Null Pointer Exc…NÃO • Uso de Option[MeuTipo] quando necessário
  • 45.
    Tipagem Estática! • Linguagenscom tipagem estáticas pegaram fama de serem verbosas • Não necessariamente • Scala consegue ser tão concisa quanto as linguagens dinâmicas • Tendência de adicionar tipos opcionais nas linguagens dinâmicas • Javascript, PHP, Python • Difícil viver sem um compilador me ajudando
  • 46.
    Imutabilidade • Coisas amenos pra guardar na sua cabeça • Não me preocupo se alguém pode ou vai mudar meu objeto • Você pode passar objetos imutáveis pra lá e pra cá de boa • Thread-safe por padrão
  • 47.
    Scala é amelhor coisa do mundo?
  • 48.
    Scala é amelhor coisa do mundo?
  • 49.
  • 50.
    Mais conciso eexpressivo que Scala é impossível
  • 51.
    Mais conciso eexpressivo que Haskell é impossível
  • 52.
    Programação é sempreum comando seguido do outro
  • 53.
    Programação pode sersó (funções (chamando (funções ‘!’))) em Clojure
  • 54.
    Ou damos free()na mão ou usamos Garbage Collector
  • 55.
    Ou damos free()na mão ou usamos Garbage Collector ou usamos Rust e o seu sistema de ownership
  • 56.
  • 57.