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
em ponto scala> 077 <console>:1: warning: Treating numbers with a leading zero as octal is deprecated. 077 ^ res10: Int = 63 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
Método Pacotes for ( val i <- 1 to 10) println(i) scala.collection.mutable.CloneableCollection scala.collection.immutable.Queue.+ scala.testing.SUnit
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
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.
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...
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???
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 IsTraversableOnce IsTraversableLike
mutable.ParArray(1, 2, 3) pc.tasksupport = new ForkJoinTaskSupport( new scala.concurrent.ForkJoinPool(2)) pc map { _ + 1) pc.tasksupport = new ThreadPoolTaskSupport()
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
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?
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!
Library”) extremamente popular Mas cerimonioso... “Extension methods” se tornando comuns em outras linguagens E com menos cerimônia! Solução: implicit class
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
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() } }
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.
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
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!
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
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!
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
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
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...
| 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>)
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 SIP-18: Modularização de Funcionalidades da Linguagem
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 SIP-18: Modularização de Funcionalidades da Linguagem
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 SIP-18: Modularização de Funcionalidades da Linguagem
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
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
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
usos de implicits continuam liberados (e incentivados!) E conversões implícitas através de classes implícitas também SIP-18: Modularização de Funcionalidades da Linguagem
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
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)
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 ^
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
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
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
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
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
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
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
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)
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?
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!)