Este documento discute o histórico e futuro da linguagem de programação Scala. Resume que Scala teve várias versões desde 2003, com melhorias contínuas. A versão 2.10.0, ainda não lançada na época, trará incompatibilidades binárias, novas depreciações e remoções, correções de bugs, e melhorias como novas coleções e desempenho.
2. Quem sou eu?
Daniel C. Sobral @ Stack Overflow
dcsobral @ Twitter, Gmail/Gtalk, Skype, SliderShare
Daniel Sobral @ Facebook, Speakers Deck, LinkedIn
http://www.linkedin.com/in/danielsobral
http://www.slideshare.net/dcsobral
https://speakerdeck.com/u/dcsobral
http://dcsobral.blogspot.com
3. O que eu sei de Scala?
Scala gold badge @ Stack Overflow
Pequenas contribuições para Scala:
otimizações
funcionalidades
bug fixes
documentação (nem tão pequenas)
Participante ativo da comunidade Scala (listas de
discussão, irc)
Blog
4. IMPORTANTE!
Scala 2.10.0 ainda não foi lançada!
Na data em que esta apresentação foi escrita...
(07/07/2012)
As informações contidas nessa apresentação podem
mudar antes do lançamento.
11. Versionamento – Scala 2.10.0
Major release
Binariamente incompatível
Mudanças de linguagem
Mudanças de biblioteca
Novas depreciações
Remoção de características depreciadas (deprecated)
Classes
Métodos
Características da linguagem
12. Exemplos de Novas Depreciações
Números octais!
scala> 077
<console>:1: warning: Treating numbers with a leading zero as octal is
deprecated.
077
^
res10: Int = 63
Double terminando em ponto
scala> 1.
<console>:1: warning: This lexical syntax is deprecated. From scala
2.11, a dot will
only be considered part of a number if it is immediately followed by
a digit.
1.
^
res11: Double = 1.0
13. Exemplos de Depreciações
Removidas
Características de linguagem
for ( val i <- 1 to 10) println(i)
Classe
scala.collection.mutable.CloneableCollection
Método
scala.collection.immutable.Queue.+
Pacotes
scala.testing.SUnit
14. Melhoria no processo de release
Processo cada vez mais automatizado
Pacotes RPM, APT, Brew, etc
Geração automática!
Uso de Milestones para integrar ferramentas de
terceiros
M4 dia 12 de Junho
M5 em breve
Release Candidates para consolidar e eliminar bugs
15. Bug fixes
Muitas correções!
Novo código do pattern matcher!
Priorização da correção de tickets!
Novos warnings:
Detectando bugs no próprio compilador!
Mais contribuições de terceiros!
git + pull request == FTW
...em adição ao processo natural de melhoria da
linguagem.
20. Novidades
Type Classes:
Try (alternativa do Twitter ao Either)
Hashing (já existe Equiv)
IsTraversableOnce e IsTraversableLike
Pacote scala.util.hashing
Pools configuráveis em coleções paralelas
@unspecialized
to[Collection]
???
21. Novidades
override object (-Yoverride-objects)
Bytecode versão 49, 50 e 51 (-target:jvm-1.x-asm)
-optimize mais rápido e eficiente
-Dscala.timings=true revela quais são os pontos de
demora na compilação
SIP-18: -language:XXX, -feature
logs variados
macro variados
patmat variados
etc...
23. scala.util.Try
Try {
new FileInputStream(a)
} rescue {
case _: FileNotFoundException =>
new FileInputStream(b)
} recover {
case _: FileNotFoundException =>
defaultInputStream
} andThen {
stream =>
in = stream.read(); Stream.close(); in
}
24. scala.util.hashing.Hashing
def hashingOf[T : Hashing](obj: T): Int =
implicitly[Hashing[T]].hash(obj)
// Uma função de hashing ruim para Seqs
implicit val seqHashing =
Hashing fromFunction ((_: Seq[_]).size)
25. IsTraversableOnce
IsTraversableLike
class FilterMapImpl[A, Repr]
(val r: GenTraversableLike[A, Repr]) {
final def filterMap[B, That]
(f: A => Option[B])
(implicit cbf: CanBuildFrom[Repr, B, That])
: That =
r.flatMap(f(_).toSeq)
}
// Como escrever a conversão implícita???
26. IsTraversableOnce
IsTraversableLike
Problemas em se escrever a conversão:
Array e String não são GenTraversable
String não possui parâmetro de elemento (A)
Nem BitSet e outras coleções
Inferência sobre view bounds é deficiente
27. IsTraversableOnce
IsTraversableLike
class FilterMapImpl[A, Repr]
(val r: GenTraversableLike[A, Repr]) {
final def filterMap[B, That]
(f: A => Option[B])
(implicit cbf: CanBuildFrom[Repr, B, That])
: That =
r.flatMap(f(_).toSeq)
}
implicit def filterMap[Repr, A](r: Repr)
(implicit fr: IsTraversableOnce[Repr])
: FilterMapImpl[fr.A,Repr] =
new FilterMapImpl(fr.conversion(r))
28. Pools Configuráveis em Coleções
Paralelas
import scala.collection.parallel._
val pc = mutable.ParArray(1, 2, 3)
pc.tasksupport = new ForkJoinTaskSupport(
new scala.concurrent.ForkJoinPool(2))
pc map { _ + 1)
pc.tasksupport = new ThreadPoolTaskSupport()
29. Pools Configuráveis em Coleções
Paralelas – Customizando
class customTaskSupport extends TaskSupport {
def execute[R, Tp]
(task: Task[R, Tp]): () => R = ???
def executeAndWaitResult[R, Tp]
(task: Task[R, Tp]): R = ???
def parallelismLevel: Int = ???
}
31. ???
??? é um método do tipo Nothing que lança uma
exceção
Por ser do tipo Nothing, ??? pode aparecer no lugar
de qualquer expressão
Excelente para stubs, exercícios e apresentações!
32. ???
trait Opt [A] { // Exercise by Tony Morris
def fold[X](some: A => X, none: => X): X = ???
def map[B](f: A => B): Opt[B] = ???
def get: A = ???
def flatMap[B](f: A => Opt[B]): Opt[B] = ???
def mapAgain[B](f: A => B): Opt[B] = ???
def getOrElse(e: => A): A = ???
def filter(p: A => Boolean): Optional[A] = ???
def exists(p: A => Boolean): Boolean = ???
def forall(p: A => Boolean): Boolean = ???
def foreach(f: A => Unit): Unit = ???
def isDefined: Boolean = ???
def orElse(o: => Opt[A]): Opt[A] = ???
// etc
Adaptado de Tony Morris, http://blog.tmorris.net/further-understanding-scalaoption/
33. ???
trait Opt [A] { // Exercise by Tony Morris
def fold[X](some: A => X, none: => X): X = ???
def map[B](f: A => B): Opt[B] = ???
def get: A = ???
def flatMap[B](f: A => Opt[B]): Opt[B] = ???
def mapAgain[B](f: A => B): Opt[B] = ???
def getOrElse(e: => A): A = ???
def filter(p: A => Boolean): Optional[A] = ???
def exists(p: A => Boolean): Boolean = ???
def forall(p: A => Boolean): Boolean = ???
def foreach(f: A => Unit): Unit = ???
def isDefined: Boolean = ???
def orElse(o: => Opt[A]): Opt[A] = ???
// etc
Adaptado de Tony Morris, http://blog.tmorris.net/further-understanding-scalaoption/
39. SIP – Scala Improvement Process
SIP-11: String Interpolation
SIP-12: Sintaxe das Estruturas de Controle
SIP-13: Classes Implicitas
SIP-14: Futures e Promises
SIP-15: Value Classes
SIP-16: Macros auto-limpantes
SIP-17: Tipo Dynamic
SIP-18: Modularização de funcionalidades da
linguagem
SIP-19: Posição de Código Fonte Implícitas
40. SIP – Scala Improvement Process
SIP-11: String Interpolation (aceita!)
SIP-12: Sintaxe das Estruturas de Controle (adiada)
SIP-13: Classes Implicitas (aceita!)
SIP-14: Futures e Promises (aceita!)
SIP-15: Value Classes (aceita!)
SIP-16: Macros auto-limpantes (adiada)
SIP-17: Tipo Dynamic (aceita!)
SIP-18: Modularização de funcionalidades da
linguagem (aceita!)
SIP-19: Posição de Código Fonte Implícitas (recusada)
41. SIP-11: String Interpolation
Ausência de interpolação de strings motivo de constante
reclamações
Mas bem poucas linguagens suportam!
Odersky diz que diferença entre ${x} e "+x+" é de um
único caracter
Mas ignora os shifts...
Alegação de que " e + no teclado Suíco não precisa de shift
Verdade!
Reviravolta:
E se interpolação de strings for mais do que interpolação de
strings?
44. SIP-11: String Interpolation:
Como funciona?
s"Hello, $name!" // traduzido para
StringContext("Hello, ", "!").s(name)
f"${ done * 100 / total }%2d% completed" // traduzido para
StringContext("", "%2d% completed").f(done * 100 / total)
45. SIP-11: String Interpolation
Literais multi-linha também são aceitos
s"""Ok!"""
Interpolação pode ser aninhada
s"${ s"$x" }"
Contra-barra não é interpretada
r"d+/$mes" // interpolador r não existe!
StringContext("""d+/""").r(mes)
Mas s e f interpretam as barras!
s"Hello, $name!n" // newline normal
Formas de alterar comportamento:
Adição de métodos implícitos à StringContext
Sobreposição de objeto ou método chamado StringContext
“r” não precisa ser método!
46. SIP-11: String Interpolation
// Adição de interpolação via implicit
class RegexContext(sc: StringContext) {
def r(args: Any*) = {
sc.checkLengths(args: _*)
val res = (args, sc.parts.tail).zipped map {
(arg, part) => s"Q$argE$part"
} mkString ""
(sc.parts.head + res).r
}
}
implicit def toRC(sc: StringContext) = new RegexContext(sc)
48. SIP-11: String Interpolation
// Adição de interpolação via sobreposição
object StringContext(parts: String*) {
def r(args: Any*) = {
require(parts.length == args.length + 1)
val res = (args, parts.tail).zipped map {
"Q" + _ + "E" + _
} mkString ""
(parts.head + res).r }
}
// Possível alterar s e f!
49. SIP-11: String Interpolation
// apply e unapplySeq
def hello(name: String = "world"): String = i"Hello, $name!"
def who(message: String): String = message match {
case i"Hello, $name!" => name
case _ => “no clue"
}
who(hello("Daniel")) == "Daniel"
50. SIP-11: String Interpolation
// apply e unapplySeq
implicit class SI(sc: StringContext) {
object i {
def apply(args: Any*): String =
sc.parts.head +
(args,sc.parts.tail).zipped.map(_+_).mkString
def unapplySeq(s: String): Option[Seq[String]] = {
val partsr = sc.parts map (p => s"Q$pE")
val r = (partsr mkString "(.*)").r
s match { case r(xs @ _*) => Some(xs) case _ => None }
}
}
}
51. SIP-13: Classes Implícitas
“Enrich My Library” (antigo “Pimp My Library”)
extremamente popular
Mas cerimonioso...
“Extension methods” se tornando comuns em outras
linguagens
E com menos cerimônia!
Solução: implicit class
52. SIP-13: Classes Implícitas
// Adição de interpolação via implicit class
implicit class RegexContext(sc: StringContext) {
def r(args: Any*) = {
sc.checkLengths(args: _*)
val res = (args, sc.parts.tail).zipped map {
"Q" + _ + "E" + _
} mkString ""
(sc.parts.head + res).r
}
}
53. SIP-14: Futures and Promises
Executar operações em paralelo, de forma não-bloqueante é
uma necessidade comum
Evidência: diversas bibliotecas contém implementações de
Future
Incluindo a biblioteca padrão de atores!
Problema:
Interface não-padronizada
Dependência de implementação
Solução:
API poderosa e flexível implementando os conceitos de
Future e Promise
54. SIP-14: Futures and Promises
// TODO – Desculpem! Exemplos da SIP:
import scala.concurrent._
val f: Future[List[String]] = future {
session.getRecentPosts
}
f onComplete {
case Right(posts) => for (post <- posts) render(post)
case Left(t) => render("An error has occured: " +
t.getMessage)
}
55. SIP-14: Futures and Promises
// TODO – Desculpem! Exemplos da SIP:
import scala.concurrent._
val f: Future[List[String]] = future {
session.getRecentPosts
}
f onFailure {
case t => render("An error has occured: " + t.getMessage)
} onSuccess {
case posts => for (post <- posts) render(post)
}
56. SIP-14: Futures and Promises
// TODO – Desculpem! Exemplos da SIP:
import scala.concurrent._
def main(args: Array[String]) {
val rateQuote = future {
connection.getCurrentValue(USD)
}
val purchase = rateQuote map {
quote => if (isProfitable(quote)) connection.buy(amount,
quote)
else throw new Exception("not profitable")
}
blocking(purchase, 0 ns)
}
57. SIP-14: Futures and Promises
// TODO – Desculpem! Exemplos da SIP:
import scala.concurrent.{ future, promise }
val p = promise[T]
val f = p.future
val producer = future {
val r = produceSomething()
p success r
continueDoingSomethingUnrelated()
}
val consumer = future {
startDoingSomething()
f onSuccess {
case r => doSomethingWithResult()
}
}
58. SIP-15: Value Classes
A maldição das referências
A maldição do boxing:
case class Meter(n: Int) muito mais “caro” que
int
A maldição do das classes implícitas:
"abc“.r cria um objeto desnecessário só para chamar new
Regex("abc")
Queremos uma classe que não seja referência!
Solução: value classes.
59. SIP-15: Value Classes
// Adição de interpolação via implicit value class
implicit class RegexContext(sc: StringContext) extends AnyVal {
def r(args: Any*) = {
sc.checkLengths(args: _*)
val res = (args, sc.parts.tail).zipped map {
"Q" + _ + "E" + _
} mkString ""
(sc.parts.head + res).r
}
}
60. SIP-15: Value Classes
Só podem ter um parâmetro
O parâmetro deve ser um val
Ou seja, [T: Ordering](v: T) não é aceito
Pode ser estendidas por traits
Se os mesmos estenderem Any ou AnyVal
Não podem definir igualdade ou hash code
Podem ser case classes!
Igualdade e hash code são aplicadas sobre o parâmetro
São efetivamente “final”
Em um escopo local, são removidas por otimização
Se escapam do escopo, são boxed
61. SIP-16: Macros
Compiladores grandes são de difícil manutenção
Pressão contra adição de funcionalidades
Plugins do compilador resolvem...
...mas são difíceis de manter em sincronia
Possível solução: Macros
“Macros? Ugh!” – trauma do C/C++!
Novidade: scala.reflection
Macros saem quase de graça!
62. SIP-16: Macros
Scala CATs!
Compile-time AST Transformations
Abstract Syntax Tree
Inspirado pelas macros de Nemerle
Quatro tipos cogitados:
Typed macros – Somente este tipo está disponível!
Untyped macros
Type (class/trait) macros
Annotation macros
63. SIP-16: Macros
// Typed macros
(1 to 5).foreach(println)
^ ^
| + Verificação de tipos
+ Macro executada
+ Nova verificação de tipos
64. SIP-16: Macros
// Untyped macros
for {val i = 0; i < 10; i += 1} println(i)
^ ^
| |
| + Tipo dos argumentos não é checado!
+ Macro executada
+ Verificação de tipos
65. SIP-16: Macros
// Untyped macros – porque?
for {val i = 0; i < 10; i += 1} println(i)
^ ^
| “i” não existe neste escopo! +
+ “i” só existe neste escopo.
66. SIP-16: Macros
// Type (class/trait) macros
class User extends DbTable(jdbcUrl, “t_user”)
^
+ Macro
// Banco de dados é consultado durante
// compilação para geração do corpo da
// classe “User”
67. SIP-16: Macros
Type macros são similares aos type providers de F#
Só que mais. ;-)
Versão experimental de SLICK (ex-ScalaQuery)
implementada com versão experimental de type
macros
68. SIP-16: Macros
// Macro annotations
@memoize
def fat(n: Int) =
if (n > 0) n * fat(n – 1)
else 1
// Macro aplicada ao elemento anotado,
// seja ele classe, método, parâmetro, etc
69. SIP-16: Macros
Somente typed macros disponibilizadas...
Experimentalmente...
Atrás do flag –language:experimental.macros...
Mas várias partes da biblioteca padrão já as estão
usando!
Por outro lado, tornar macros fáceis não foi um dos
objetivos...
De propósito...
Trauma das “macros” do C/C++ muito difuso...
...mas as verdadeiras macros do C++ são os templates!
70. SIP-16: Macros
Vantagens de Typed Macros:
Relativamente simples de implementar
Assinatura de método implementado com macro não
tem nenhuma diferença!
Facilidade para testar
Higiene provida através de macro!
Macros não higiênicas fáceis de criar
71. SIP-16: Macros
Desvantagens:
Limites no que é possível
Compilação em dois estágios
Não é possível compilar uma macro e usá-la em um único
passo
Não-higienica por default
Quem é do contra vai continuar achando ruim
73. SIP-16: Macros
Tipos de métodos dependentes de tipos:
def m(c: Context)(param: c.Expr[Any]):
c.Expr[Any]
Opção –Ydependent-method-types em versões
anteriores
Reflexão, reflexão e reflexão!
“Uma vez que temos reflexão direito, macros vem de
graça!” – parafraseando Martin Odersky
74. SIP-17: Tipo Dynamic
Problema: a integração de Scala com outras linguagens
assume tipagem estática
Grande quantidade de alternativas dinâmicas na JVM!
Solução: trait Dynamic
Similar ao “missing method”
Facilita integração com linguagens dinâmicas na JVM
Mas tem outras utilidades...
75. SIP-17: Tipo Dynamic
scala> class xmlPath(xml: scala.xml.Node) extends Dynamic {
| def selectDynamic(path: String) = xml path
| }
defined class xmlPath
scala> new xmlPath(<root><a><b><c/></b></a></root>).b
res9: scala.xml.NodeSeq = NodeSeq(<b><c/></b>)
76. SIP-17: Tipo Dynamic
Conversões:
Métodos convencionais:
applyDynamic
Métodos com nome de parâmetros:
applyDynamicNamed
Atribuições (setters):
updateDynamic
Valores (getters):
selectDynamic
77. SIP-18: Modularização de
Funcionalidades da Linguagem
Problemas:
Algumas funcionalidades de Scala são de difícil
compreensão
Outras induzem a erros
E algumas são experimentais
Mas são todas necessárias, por uma razão ou outra!
Solução: SIP-18
78. SIP-18: Modularização de
Funcionalidades da Linguagem
Controla acesso a certas funcionalidades
Uso das funcionalidades causa avisos
Mas podem se tornar erros em futuras versões
Liberação de uso através de:
flag de compilação
valor implícito no escopo
Liberação pode ser herdada
ScalaDoc explica prós e contras de cada funcionalidade
79. SIP-18: Modularização de
Funcionalidades da Linguagem
Funcionalidades contenciosas
Operadores pós-fixados
Chamada de métodos implementadas via reflexão
Conversões de tipo implícitas
Higher kinded types
Existenciais
Exceto aqueles que equivalem a Java wildcard types
Tipo Dynamic
Funcionalidades experimentais
Macros
80. SIP-18: Modularização de
Funcionalidades da Linguagem
// Notação de operador pós-fixado
scala> "abc" length
warning: there were 1 feature warnings; re-run with -feature for
details
res0: Int = 3
81. SIP-18: Modularização de
Funcionalidades da Linguagem
// Notação de operador pós-fixado, com –feature
scala> "abc" length
<console>:8: warning: postfix operator length should be enabled
by making the implicit value language.postfixOps visible.
This can be achieved by adding the import clause 'import
language.postfixOps'
or by setting the compiler option -language:postfixOps.
See the Scala docs for value scala.language.postfixOps for a
discussion
why the feature should be explicitly enabled.
"abc" length
^
res0: Int = 3
82. SIP-18: Modularização de
Funcionalidades da Linguagem
// Chamada de métodos implementadas via reflexão
scala> val x = new AnyRef { def hello = println("world") }
x: Object{def hello: Unit} = $anon$1@7d628303
scala> x.hello
<console>:10: warning: reflective access of structural type member method hello
should
be enabled
by making the implicit value language.reflectiveCalls visible.
This can be achieved by adding the import clause 'import language.reflectiveCalls'
or by setting the compiler option -language:reflectiveCalls.
See the Scala docs for value scala.language.reflectiveCalls for a discussion
why the feature should be explicitly enabled.
x.hello
^
world
83. SIP-18: Modularização de
Funcionalidades da Linguagem
// Conversões Implícitas
scala> implicit def f(s: String): Int = Predef.augmentString(s).toInt
<console>:8: warning: implicit conversion method f should be enabled
by making the implicit value language.implicitConversions visible.
This can be achieved by adding the import clause 'import
language.implicitConversions'
or by setting the compiler option -language:implicitConversions.
See the Scala docs for value scala.language.implicitConversions for a
discussion
why the feature should be explicitly enabled.
implicit def f(s: String): Int = Predef.augmentString(s).toInt
^
f: (s: String)Int
84. SIP-18: Modularização de
Funcionalidades da Linguagem
A funcionalidade limitada são as conversões
implícitas
Outros usos de implicits continuam liberados (e
incentivados!)
E conversões implícitas através de classes implícitas
também
85. SIP-18: Modularização de
Funcionalidades da Linguagem
// Higher Kinded Types
scala> class Monad[M[_]]
<console>:9: warning: higher-kinded type should be enabled
by making the implicit value language.higherKinds visible.
This can be achieved by adding the import clause 'import
language.higherKinds'
or by setting the compiler option -language:higherKinds.
See the Scala docs for value scala.language.higherKinds for a
discussion
why the feature should be explicitly enabled.
class Monad[M[_]]
^
defined class Monad
86. SIP-18: Modularização de
Funcionalidades da Linguagem
// Existenciais
scala> val l: List[ T forSome { type T }] = List(1)
<console>:7: warning: the existential type T forSome { type T
}, which cannot be expressed by wildcards, should be enabled
by making the implicit value language.existentials visible.
This can be achieved by adding the import clause 'import
language.existentials'
or by setting the compiler option -language:existentials.
See the Scala docs for value scala.language.existentials for a
discussion
why the feature should be explicitly enabled.
val l: List[ T forSome { type T }] = List(1)
^
l: List[T forSome { type T }] = List(1)
88. SIP-18: Modularização de
Funcionalidades da Linguagem
// Macros
scala> def g(d: Any): Any = macro f
<console>:12: error: macro definition needs to be enabled
by making the implicit value language.experimental.macros
visible.
This can be achieved by adding the import clause 'import
language.experimental.macros'
or by setting the compiler option -language:experimental.macros.
See the Scala docs for value scala.language.experimental.macros
for a discussion
why the feature needs to be explicitly enabled.
def g(d: Any): Any = macro f
^
89. scala.reflect
Permitem explorar a estrutura de um programa,
e interagir com esta estrutura
Wiki: reflexão ocorre em tempo de execução
Scala: você usa a mesma biblioteca em tempo de
compilação, com macros
Noções fundamentais:
Bibliotecas de reflexão e Universos
Nomes, símbolos, tipos, árvores
Mirrors
91. scala.reflect – Universos
Contém uma série de elementos interligados que,
juntos, formam os componentes fundamentais da
reflexão
Symbol
Tree
Name
etc...
Uso de path dependent types para associar tipos aos
universos dos quais se originaram
92. scala.reflect – Universos
Construído com o “cake pattern” em camadas com
diferentes graus de detalhes:
Base:
Conceito fundamentais
Identidade, e pouco mais
JavaUniverse
Manipulação baseada nas facilidades de reflexão provida pela JVM,
melhorada com informações de Scala
Makro
Manipulação em tempo de compilação
Universo do compilador, mas com uma API mais restrita
Outros: Compilador
93. scala.reflect – Tipos Fundamentais
Name
FlagSet Symbol
Universo
AnnotationInfo
Type
Position Tree
95. scala.reflect – Name
Scala possui dois espaços de nome:
Tipos
Valores (Term)
Name associa uma string a um desses dois espaços
Name também permite converter entre a representação
na linguagem, e a representação nos class files
97. scala.reflect – Symbol
Todas definições estão associadas a símbolos
Classes
Métodos
Parâmetros
Variáveis
Se você deu um nome, tem um símbolo
Se você não deu um nome, mas chama de “anônimo”,
tem um símbolo também
Mutável no compilador, imutável em tempo de
execução
98. scala.reflect – Type
Representa a estrutura associada a um tipo:
Membros das classes
Parâmetros e tipo de retorno de um método
etc
Formado por case classes imutáveis
Manipulado através de pattern matching
99. scala.reflect – Tipos e Símbolos
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> typeOf[List[Int]]
res0: reflect.runtime.universe.Type = List[Int]
scala> res0.member(newTermName("head"))
res1: reflect.runtime.universe.Symbol = method head
scala> res1.typeSignature
res2: reflect.runtime.universe.Type = => A
scala> res1.typeSignatureIn(res0)
res3: reflect.runtime.universe.Type = => Int
100. scala.reflect – Tipos e Símbolos
def intMethods[T : TypeTag](v: T) = {
val IntType = typeOf[Int]
val vType = typeOf[T]
val methods = vType.nonPrivateMembers.collect {
case m: MethodSymbol => m -> m.typeSignatureIn(vType)
}
methods collect {
case (m, mt @ NullaryMethodType(IntType)) => m -> mt
case (m, mt @ MethodType(_, IntType)) => m -> mt
case (m, mt @ PolyType(_, MethodType(_, IntType))) => m -> mt
}
}
101. scala.reflect – Tipos e Símbolos
def intMethods[T : TypeTag](v: T) = {
val IntType = typeOf[Int]
val vType = typeOf[T]
val methods = vType.nonPrivateMembers.collect {
case m: MethodSymbol => m -> m.typeSignatureIn(vType)
}
methods collect {
case (m, mt @ NullaryMethodType(IntType)) => m -> mt
case (m, mt @ MethodType(_, IntType)) => m -> mt
case (m, mt @ PolyType(_, MethodType(_, IntType))) => m -> mt
}
}
102. scala.reflect – Tipos e Símbolos
// Na verdade, você precisa disso:
case (m, mt @ NullaryMethodType(tpe)) if tpe =:= IntType =>
103. scala.reflect – Tree
TypTree Tree TermTree
children Type Position Symbol
Tree Tree ... Tree
104. scala.reflect – Tree
São a representação interna do compilador do código
fonte
Imutável, formado por case classes
Essencial ao se lidar com macros
Usado para annotated typed na biblioteca básica
105. scala.reflect – Tree
scala> import scala.tools.reflect.ToolBox
import scala.tools.reflect.ToolBox
scala> import scala.reflect.runtime.{currentMirror => m}
import scala.reflect.runtime.{currentMirror=>m}
scala> val tb = m.mkToolBox()
tb: scala.tools.reflect.ToolBox[reflect.runtime.universe.type] =
scala.tools.reflect.ToolBoxFactory$ToolBoxImpl@5bbdee69
scala> val tree = tb.parseExpr("1 to 3 map (_+1)")
tree: tb.u.Tree = 1.to(3).map(((x$1) => x$1.$plus(1)))
scala> val eval = tb.runExpr(tree)
eval: Any = Vector(2, 3, 4)
108. scala.reflect – Mirror
Mirrors permitem manipulação de instâncias e classes
em tempo de execução
Cada Universe pode ter um ou mais mirrors
Cada mirror está associado a um class loader
Classes de mesmo nome podem existir carregadas por
class loaders distintos
Mirrors permitem manipulação baseada na linguagem
Scala, e não em sua implementação na JVM
109. scala.reflect – Mirror
val obj = "String"
val objClass = obj.getClass
val classClassLoader = objClass.getClassLoader
val classLoaderMirror = runtimeMirror(classClassLoader)
val classSymbol = classLoaderMirror.classSymbol(objClass)
val classType = classSymbol.typeSignature
val methodName = newTermName("length")
val methodSymbol = classType.member(methodName).asMethodSymbol
val instanceMirror = classLoaderMirror.reflect(obj)
val methodMirror = instanceMirror.reflectMethod(methodSymbol)
methodMirror.apply() // == (obj.length: Any)
110. Atores e Akka???
A biblioteca padrão deixará de existir
Substituída pelo Akka
Quando???
A biblioteca Akka fará parte da distribuição 2.10
Somente binários – código fonte permanece separado
Será disponibilizado um guia de migração
A biblioteca padrão virá com um “kit” para facilitar a
migração
Para que serve?
112. Especulações
untyped macros
for { val x = 0; x < 10; x += 1 } println(x)
macro types
class X extends MacroClassY(parm)
macro annotations
@memoize def fat(n: Int) = if (n > 0) n *
fat(n -1) else 1
effect system
integração de abstract types e type parameters.
pré-processador (DOA!)