Scala Cheatsheet
Scala Cheatsheet
Language
Contribuição de Reginaldo Russinholi
Agradecimentos a Brendan O’Connor, este ‘cheatsheet’ se destina a ser uma referência rápida às construções sintáticas de Scala. Licenciado por Brendan O’Connor sobre a licença CC-BY-SA 3.0.
variáveis | |
var x = 5 |
variável |
Bom val x = 5 Ruim x=6 |
constante |
var x: Double = 5 |
tipo explícito |
funções | |
Bom def f(x: Int) = { x*x } Ruim def f(x: Int) { x*x } |
define uma função erro omitido: sem = é uma procedure que retorna Unit; causa dano |
Bom def f(x: Any) = println(x) Ruim def f(x) = println(x) |
define uma função erro de sintaxe: necessita tipos para todos os argumentos. |
type R = Double |
alias de tipo |
def f(x: R) vs.def f(x: => R) |
chamada-por-valor chamada-por-nome (parâmetros ‘lazy’) |
(x:R) => x*x |
função anônima |
(1 to 5).map(_*2) vs.(1 to 5).reduceLeft( _+_ ) |
função anônima: ‘underscore’ está associado a posição do argumento. |
(1 to 5).map( x => x*x ) |
função anônima: para usar um argumento duas vezes, tem que dar nome a ele. |
Bom (1 to 5).map(2*) Ruim (1 to 5).map(*2) |
função anônima: método infixo encadeado. Use 2*_ para ficar mais claro. |
(1 to 5).map { val x=_*2; println(x); x } |
função anônima: estilo em bloco retorna a última expressão. |
(1 to 5) filter {_%2 == 0} map {_*2} |
função anônima: estilo ‘pipeline’. (ou também parênteses). |
def compose(g:R=>R, h:R=>R) = (x:R) => g(h(x)) val f = compose({_*2}, {_-1}) |
função anônima: para passar múltiplos blocos é necessário colocar entre parênteses. |
val zscore = (mean:R, sd:R) => (x:R) => (x-mean)/sd |
currying, sintáxe óbvia. |
def zscore(mean:R, sd:R) = (x:R) => (x-mean)/sd |
currying, sintáxe óbvia |
def zscore(mean:R, sd:R)(x:R) = (x-mean)/sd |
currying, sintáxe ‘sugar’. mas então: |
val normer = zscore(7, 0.4)_ |
precisa de ‘underscore’ no final para obter o parcial, apenas para a versão ‘sugar’. |
def mapmake[T](g:T=>T)(seq: List[T]) = seq.map(g) |
tipo genérico. |
5.+(3); 5 + 3 (1 to 5) map (_*2) |
sintáxe ‘sugar’ para operadores infixos. |
def sum(args: Int*) = args.reduceLeft(_+_) |
varargs. |
pacotes | |
import scala.collection._ |
caracter coringa para importar tudo de um pacote. |
import scala.collection.Vector import scala.collection.{Vector, Sequence} |
importação seletiva. |
import scala.collection.{Vector => Vec28} |
renomear uma importação. |
import java.util.{Date => _, _} |
importar tudo de java.util exceto Date. |
package pkg no início do arquivo package pkg { ... } |
declara um pacote. |
estruturas de dados | |
(1,2,3) |
literal de tupla. (Tuple3 ) |
var (x,y,z) = (1,2,3) |
atribuição desestruturada: desempacotando uma tupla através de “pattern matching”. |
Ruimvar x,y,z = (1,2,3) |
erro oculto: cada variável é associada a tupla inteira. |
var xs = List(1,2,3) |
lista (imutável). |
xs(2) |
indexação por parênteses. (slides) |
1 :: List(2,3) |
concatenação. |
1 to 5 o mesmo que 1 until 6 1 to 10 by 2 |
sintáxe ‘sugar’ para intervalo. |
() (parênteses vazio) |
um membro do tipo Unit (igual ao void de C/Java). |
estruturas de controle | |
if (check) happy else sad |
condicional. |
if (check) happy o mesmo que if (check) happy else () |
condicional ‘sugar’. |
while (x < 5) { println(x); x += 1} |
while. |
do { println(x); x += 1} while (x < 5) |
do while. |
import scala.util.control.Breaks._ breakable { for (x <- xs) { if (Math.random < 0.1) break } } |
break. (slides) |
for (x <- xs if x%2 == 0) yield x*10 o mesmo que xs.filter(_%2 == 0).map(_*10) |
for: filter/map |
for ((x,y) <- xs zip ys) yield x*y o mesmo que (xs zip ys) map { case (x,y) => x*y } |
for: associação desestruturada |
for (x <- xs; y <- ys) yield x*y o mesmo que xs flatMap {x => ys map {y => x*y}} |
for: produto cruzado |
for (x <- xs; y <- ys) { println("%d/%d = %.1f".format(x, y, x/y.toFloat)) } |
for: estilo imperativo sprintf-style |
for (i <- 1 to 5) { println(i) } |
for: itera incluindo o limite superior |
for (i <- 1 until 5) { println(i) } |
for: itera omitindo o limite superior |
pattern matching | |
Bom (xs zip ys) map { case (x,y) => x*y } Ruim (xs zip ys) map( (x,y) => x*y ) |
use ‘case’ nos argumentos de funções para fazer a associação via ‘pattern matching’. |
Ruimval v42 = 42 Some(3) match { case Some(v42) => println("42") case _ => println("Not 42") } |
“v42” é interpretado como um nome que será comparado com qualquer valor Int, e “42” é impresso. |
Bomval v42 = 42 Some(3) match { case Some(`v42`) => println("42") case _ => println("Not 42") } |
”`v42`” entre crases é interpretado como existindo o valor v42 , e “Not 42” é impresso. |
Bomval UppercaseVal = 42 Some(3) match { case Some(UppercaseVal) => println("42") case _ => println("Not 42") } |
UppercaseVal é tratado como um valor existente, mais do que uma nova variável de padrão, porque ele inicia com uma letra maiúscula. Assim, o valor contido em UppercaseVal é checado contra 3 , e “Not 42” é impresso. |
orientação a objetos | |
class C(x: R) o mesmo que class C(private val x: R) var c = new C(4) |
parâmetros do construtor - privado |
class C(val x: R) var c = new C(4) c.x |
parâmetros do construtor - público |
class C(var x: R) { assert(x > 0, "positive please") var y = x val readonly = 5 private var secret = 1 def this = this(42) } |
o construtor é o corpo da classe declara um membro público declara um membro que pode ser obtido mas não alterado declara um membro privado construtor alternativo |
new{ ... } |
classe anônima |
abstract class D { ... } |
define uma classe abstrata. (que não pode ser instanciada) |
class C extends D { ... } |
define uma classe com herança. |
class D(var x: R) class C(x: R) extends D(x) |
herança e parâmetros do construtor. (lista de desejos: automaticamente passar parâmetros por ‘default’) |
object O extends D { ... } |
define um ‘singleton’. (module-like) |
trait T { ... } class C extends T { ... } class C extends D with T { ... } |
traits. interfaces-com-implementação. sem parâmetros de construtor. mixin-able. |
trait T1; trait T2 class C extends T1 with T2 class C extends D with T1 with T2 |
multiplos traits. |
class C extends D { override def f = ...} |
é necessário declarar a sobrecarga de métodos. |
new java.io.File("f") |
cria/instancia um objeto. |
Ruim new List[Int] Bom List(1,2,3) |
erro de tipo: tipo abstrato ao invés, por convenção: a ‘factory’ chamada já aplica o tipo implicitamente |
classOf[String] |
literal de classe. |
x.isInstanceOf[String] |
checagem de tipo (em tempo de execução) |
x.asInstanceOf[String] |
conversão/’cast’ de tipo (em tempo de execução) |
x: String |
atribuição de tipo (em tempo de compilação) |