112
Scala 2.10 De onde viemos e para onde vamos? Daniel Capó Sobral

Scala 2.10.0

Embed Size (px)

DESCRIPTION

Scala 2.10.0 -- de onde viemos, e para onde vamos? Breve olhar nas funcionalidades a serem introduzidas por Scala 2.10.0. Nota: Scala 2.10.0 não foi lançada, e a versão final terá diferenças em relação ao apresentado.

Citation preview

Page 1: Scala 2.10.0

Scala 2.10De onde viemos e para onde vamos?

Daniel Capó Sobral

Page 2: Scala 2.10.0

Quem sou eu?Daniel C. Sobral @ Stack Overflowdcsobral @ Twitter, Gmail/Gtalk, Skype,

SliderShareDaniel Sobral @ Facebook, Speakers Deck,

LinkedInhttp://www.linkedin.com/in/danielsobralhttp://www.slideshare.net/dcsobralhttps://speakerdeck.com/u/dcsobralhttp://dcsobral.blogspot.com

Page 3: Scala 2.10.0

O que eu sei de Scala?Scala gold badge @ Stack OverflowPequenas contribuições para Scala:

otimizaçõesfuncionalidadesbug fixesdocumentação (nem tão pequenas)

Participante ativo da comunidade Scala (listas de discussão, irc)

Blog

Page 4: Scala 2.10.0

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.

Page 5: Scala 2.10.0

SumárioHistóricoFuturo Imediato

VersionamentoProcesso de ReleaseBug fixesMelhoriasSIPs (Scala Improvement Process)ReflectionAtores e Akka

Futuro Distante

Page 6: Scala 2.10.0

O passado

Page 7: Scala 2.10.0

Histórico

• 2.9.2

2012

• 2.9.0

• 2.9.1

• 2.8.2

2011

• 2.8.0

• 2.8.1

2010

• 2.7.3

• 2.7.4

• 2.7.5

• 2.7.6

• 2.7.7

2009

• 2.7.1

• 2.7.2

2008

• 2.3.2

• 2.3.3

• 2.4.0

• 2.5.0

• 2.5.1

• 2.6.0

• 2.6.1

2007

• 2.0.0

• 2.1.0

• 2.1.1

• 2.1.2

• 2.1.3

• 2.1.5

• 2.1.6

• 2.1.7

• 2.1.8

• 2.2.0

• 2.3.0

• 2.3.1

2006

• 1.4.0

2005

• 1.0.0

• 1.1.0

• 1.1.0

• 1.1.1

• 1.2.0

• 1.3.0

2004

• 0.8.1

• 0.8.2

• 0.9.0

• 0.9.1

2003

Page 8: Scala 2.10.0

Alguns marcos importantes

2006• Scalac escrito em Scala

• Implicits• Traits e linearização

• Multilline Strings

2007• Extractors• Private/protected primary constructors

• Private[this]• Placeholder parameters

• Early Initialization• Abstract Type Constructors

• Existential Types• Lazy values• Structural Types

2008• Java Generics• Case Class Extractors

2010• Novo design de Collections

• Compatibilidade Binária

2011• Parallel Collections

Page 9: Scala 2.10.0

O futuro imediato

Page 10: Scala 2.10.0

Explicando Versionamento

2

Epoch

.9

Major

.1

Minor

-1

Bug fix

Page 11: Scala 2.10.0

Versionamento – Scala 2.10.0Major releaseBinariamente incompatívelMudanças de linguagemMudanças de bibliotecaNovas depreciaçõesRemoção de características depreciadas

(deprecated)ClassesMétodosCaracterísticas da linguagem

Page 12: Scala 2.10.0

Exemplos de Novas DepreciaçõesNúmeros octais!

Double terminando 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 willonly be considered part of a number if it is immediately followed by a digit. 1. ^res11: Double = 1.0

Page 13: Scala 2.10.0

Exemplos de Depreciações RemovidasCaracterísticas de linguagem

Classe

Método

Pacotes

for ( val i <- 1 to 10) println(i)

scala.collection.mutable.CloneableCollection

scala.collection.immutable.Queue.+

scala.testing.SUnit

Page 14: Scala 2.10.0

Melhoria no processo de releaseProcesso cada vez mais automatizadoPacotes RPM, APT, Brew, etc

Geração automática!Uso de Milestones para integrar ferramentas

de terceirosM4 dia 12 de JunhoM5 em breve

Release Candidates para consolidar e eliminar bugs

Page 15: Scala 2.10.0

Bug fixesMuitas 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.

Page 16: Scala 2.10.0

Tickets fechados102 451 490 622 896 963 1118 1133 1195 1201 1247 1336

1430 1431 1432 1439 1510 1785 1799 2089 2094 2171 2196 2308

2322 2337 2388 2405 2435 2442 2460 2764 2782 2807 3047 3048

3098 3240 3272 3326 3343 3371 3392 3481 3566 3569 3628 3702

3708 3718 3755 3758 3761 3770 3798 3853 3854 3880 3898 3929

3960 3999 4018 4019 4025 4027 4063 4070 4098 4110 4124 4134

4147 4171 4172 4176 4216 4262 4270 4271 4273 4319 4326 4336

4355 4372 4391 4398 4417 4419 4425 4430 4441 4461 4467 4469

4478 4482 4490 4494 4501 4510 4512 4515 4535 4540 4541 4542

4547 4553 4561 4568 4570 4573 4574 4578 4579 4584 4592 4593

4595 4599 4601 4627 4636 4642 4647 4651 4656 4658 4661 4692

4696 4697 4709 4712 4713 4716 4717 4723 4727 4731 4737 4740

4749 4753 4757 4758 4759 4761 4764 4766 4770 4777 4780 4792

Page 17: Scala 2.10.0

Tickets fechados4794 4800 4802 4804 4807 4809 4811 4818 4823 4827 4828 4831

4833 4839 4842 4846 4851 4853 4857 4858 4859 4860 4861 4869

4871 4874 4875 4877 4879 4882 4891 4894 4898 4899 4909 4910

4911 4925 4928 4929 4933 4935 4938 4954 4957 4959 4961 4963

4970 4975 4976 4979 4981 4985 4987 4989 5005 5009 5012 5018

5020 5023 5026 5029 5032 5033 5034 5037 5040 5041 5053 5054

5056 5062 5063 5066 5071 5072 5077 5078 5080 5083 5084 5085

5093 5096 5097 5099 5104 5105 5108 5117 5119 5121 5125 5127

5135 5137 5147 5148 5152 5156 5162 5165 5167 5168 5175 5176

5178 5189 5199 5201 5205 5206 5210 5212 5215 5223 5226 5229

5230 5239 5245 5248 5256 5259 5266 5267 5272 5284 5287 5291

5293 5295 5300 5305 5313 5317 5318 5328 5334 5336 5341 5343

5344 5352 5354 5356 5358 5359 5373 5374 5375 5377 5382 5384

Page 18: Scala 2.10.0

Tickets fechados (442 – 02/Jul)5387 5399 5405 5406 5407 5426 5428 5429 5441 5444 5446 5451

5452 5453 5455 5471 5488 5489 5497 5500 5510 5514 5522 5528

5530 5532 5535 5537 5542 5543 5544 5545 5552 5553 5554 5564

5571 5572 5577 5578 5580 5589 5590 5591 5593 5599 5608 5609

5610 5612 5614 5617 5623 5626 5627 5629 5632 5640 5641 5644

5648 5652 5654 5655 5656 5663 5666 5667 5672 5676 5677 5680

5682 5683 5688 5689 5690 5693 5696 5702 5703 5704 5706 5707

5708 5713 5715 5720 5728 5729 5735 5738 5742 5760 5761 5763

5769 5777 5779 5796 5801 5804 5805 5809 5816 5821 5829 5839

5840 5843 5845 5846 5853 5857 5862 5867 5879 5880 5881 5899

5910 5912 5914 5932 5953 5966 5967 5968 5971 5986 etc?

Page 19: Scala 2.10.0

MelhoriasNovas coleções

Mutable SortedSet/SortedMap (baseadas em AVL)Mutable Concurrent Map (TrieMap)Parallel Mutable Concurrent Map (ParTrieMap)

Performance:Immutable SortedSet/SortedMap

Novo (private) RedBlackTree TreeIterator

PartialFunction applyOrElse

BitSetMurmurHash3 (coleções, xml, case classes)

Page 20: Scala 2.10.0

NovidadesType Classes:

Try (alternativa do Twitter ao Either)Hashing (já existe Equiv)IsTraversableOnce e IsTraversableLike

Pacote scala.util.hashingPools configuráveis em coleções paralelas@unspecializedto[Collection]???

Page 21: Scala 2.10.0

Novidadesoverride 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çãoSIP-18: -language:XXX, -featurelogs variadosmacro variadospatmat variadosetc...

Page 22: Scala 2.10.0

scala.util.Try

def percentCompleted(total: Int, done: Int): Int = Try ( done * 100 / total ) getOrElse 100

Page 23: Scala 2.10.0

scala.util.TryTry { new FileInputStream(a)} rescue { case _: FileNotFoundException => new FileInputStream(b)} recover { case _: FileNotFoundException => defaultInputStream} andThen { stream => in = stream.read(); Stream.close(); in}

Page 24: Scala 2.10.0

scala.util.hashing.Hashing

def hashingOf[T : Hashing](obj: T): Int = implicitly[Hashing[T]].hash(obj)

// Uma função de hashing ruim para Seqsimplicit val seqHashing = Hashing fromFunction ((_: Seq[_]).size)

Page 25: Scala 2.10.0

IsTraversableOnceIsTraversableLike

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???

Page 26: Scala 2.10.0

Problemas em se escrever a conversão:Array e String não são GenTraversableString não possui parâmetro de elemento (A)Nem BitSet e outras coleçõesInferência sobre view bounds é deficiente

IsTraversableOnceIsTraversableLike

Page 27: Scala 2.10.0

IsTraversableOnceIsTraversableLike

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))

Page 28: Scala 2.10.0

Pools Configuráveis em Coleções Paralelasimport 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()

Page 29: Scala 2.10.0

Pools Configuráveis em Coleções Paralelas – Customizandoclass customTaskSupport extends TaskSupport { def execute[R, Tp] (task: Task[R, Tp]): () => R = ???

def executeAndWaitResult[R, Tp] (task: Task[R, Tp]): R = ???

def parallelismLevel: Int = ???}

Page 30: Scala 2.10.0

to[Collection]scala> List(2, 1, 3).to[Seq]res17: Seq[Int] = Vector(2, 1, 3)

scala> List(2, 1, 3).to[Vector]res18: Vector[Int] = Vector(2, 1, 3)

scala> List(2, 1, 3).to[collection.mutable.Seq]res19: scala.collection.mutable.Seq[Int] = ArrayBuffer(2, 1, 3)

scala> List(2, 1, 3).to[collection.immutable.SortedSet]res20: scala.collection.immutable.SortedSet[Int] = TreeSet(1, 2, 3)

Page 31: Scala 2.10.0

?????? é um método do tipo Nothing que lança

uma exceçãoPor ser do tipo Nothing, ??? pode aparecer

no lugar de qualquer expressãoExcelente para stubs, exercícios e

apresentações!

Page 32: Scala 2.10.0

???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/

Page 33: Scala 2.10.0

???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/

Page 34: Scala 2.10.0

MelhoriasScaladoc

Implicits!Diagramas!

API docs

Page 35: Scala 2.10.0

ScalaDoc & Implicits

Page 36: Scala 2.10.0

Parallel Collections Docs!

Page 37: Scala 2.10.0

Diagramas de Classe!

Page 38: Scala 2.10.0

Parâmetros para ScalaDoc-implicits-diagrams

Esse slide foi exigência de Vlad Ureche ;-)

Page 39: Scala 2.10.0

SIP – Scala Improvement ProcessSIP-11: String InterpolationSIP-12: Sintaxe das Estruturas de ControleSIP-13: Classes ImplicitasSIP-14: Futures e PromisesSIP-15: Value ClassesSIP-16: Macros auto-limpantesSIP-17: Tipo DynamicSIP-18: Modularização de funcionalidades da

linguagemSIP-19: Posição de Código Fonte Implícitas

Page 40: Scala 2.10.0

SIP – Scala Improvement ProcessSIP-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)

Page 41: Scala 2.10.0

SIP-11: String InterpolationAusência de interpolação de strings motivo de

constante reclamaçõesMas bem poucas linguagens suportam!

Odersky diz que diferença entre ${x} e "+x+" é de um único caracterMas 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?

Page 42: Scala 2.10.0

SIP-11: String Interpolationdef hello(name: String = "world"): String = "Hello, " + name + "! "

// Interpolation!def hello(name: String = "world"): String = s"Hello, $name! "

Page 43: Scala 2.10.0

SIP-11: String Interpolationdef percentCompleted(total: Int, done: Int): String = Try ( done * 100 / total ) map { percent => f"$percent%2d% completed" } getOrElse "100% completed"

def percentCompleted(total: Int, done: Int): String = Try ( f"${ done * 100 / total }%2d% completed" ) getOrElse "100% completed"

Page 44: Scala 2.10.0

SIP-11: String Interpolation:Como funciona?s"Hello, $name!" // traduzido paraStringContext("Hello, ", "!").s(name)

f"${ done * 100 / total }%2d% completed" // traduzido paraStringContext("", "%2d% completed").f(done * 100 / total)

Page 45: Scala 2.10.0

SIP-11: String InterpolationLiterais 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 à StringContextSobreposição de objeto ou método chamado StringContext“r” não precisa ser método!

Page 46: Scala 2.10.0

SIP-11: String Interpolation// Adição de interpolação via implicitclass RegexContext(sc: StringContext) { def r(args: Any*) = { sc.checkLengths(args: _*) val res = (args, sc.parts.tail).zipped map { (arg, part) => s"\\Q$arg\\E$part" } mkString "" (sc.parts.head + res).r }}

implicit def toRC(sc: StringContext) = new RegexContext(sc)

Page 47: Scala 2.10.0

SIP-11: String Interpolation// Aninhamento de interpoladoresclass RegexContext(sc: StringContext) { def r(args: Any*) = { sc.checkLengths(args: _*) s"${sc.parts.head}${ (args, sc.parts.tail).zipped map { (arg, part) => s"\\Q$arg\\E$part" } mkString "" }".r }}

implicit def toRC(sc: StringContext) = new RegexContext(sc)

Page 48: Scala 2.10.0

SIP-11: String Interpolation// Adição de interpolação via sobreposiçãoobject 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!

Page 49: Scala 2.10.0

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"

Page 50: Scala 2.10.0

SIP-11: String Interpolation// apply e unapplySeqimplicit 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$p\\E") val r = (partsr mkString "(.*)").r s match { case r(xs @ _*) => Some(xs) case _ => None } } }}

Page 51: Scala 2.10.0

SIP-13: Classes Implícitas“Enrich My Library” (antigo “Pimp My

Library”) extremamente popularMas cerimonioso...“Extension methods” se tornando comuns em

outras linguagensE com menos cerimônia!

Solução: implicit class

Page 52: Scala 2.10.0

SIP-13: Classes Implícitas// Adição de interpolação via implicit classimplicit 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 }}

Page 53: Scala 2.10.0

SIP-14: Futures and PromisesExecutar operações em paralelo, de forma não-

bloqueante é uma necessidade comumEvidência: diversas bibliotecas contém

implementações de FutureIncluindo a biblioteca padrão de atores!

Problema:Interface não-padronizadaDependência de implementação

Solução:API poderosa e flexível implementando os

conceitos de Future e Promise

Page 54: Scala 2.10.0

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)}

Page 55: Scala 2.10.0

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)}

Page 56: Scala 2.10.0

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)}

Page 57: Scala 2.10.0

SIP-14: Futures and Promises// TODO – Desculpem! Exemplos da SIP:

import scala.concurrent.{ future, promise }val p = promise[T]val f = p.futureval producer = future { val r = produceSomething() p success r continueDoingSomethingUnrelated()}val consumer = future { startDoingSomething() f onSuccess { case r => doSomethingWithResult() }}

Page 58: Scala 2.10.0

SIP-15: Value ClassesA maldição das referênciasA 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.

Page 59: Scala 2.10.0

SIP-15: Value Classes// Adição de interpolação via implicit value classimplicit 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 }}

Page 60: Scala 2.10.0

SIP-15: Value ClassesSó podem ter um parâmetro

O parâmetro deve ser um valOu seja, [T: Ordering](v: T) não é aceitoPode ser estendidas por traits

Se os mesmos estenderem Any ou AnyValNão podem definir igualdade ou hash code

Podem ser case classes!Igualdade e hash code são aplicadas sobre o

parâmetroSão efetivamente “final”Em um escopo local, são removidas por otimizaçãoSe escapam do escopo, são boxed

Page 61: Scala 2.10.0

SIP-16: MacrosCompiladores grandes são de difícil

manutençãoPressã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.reflectionMacros saem quase de graça!

Page 62: Scala 2.10.0

SIP-16: MacrosScala CATs!

Compile-time AST Transformations Abstract Syntax Tree

Inspirado pelas macros de NemerleQuatro tipos cogitados:

Typed macros – Somente este tipo está disponível!

Untyped macrosType (class/trait) macrosAnnotation macros

Page 63: Scala 2.10.0

SIP-16: Macros// Typed macros

(1 to 5).foreach(println) ^ ^ | + Verificação de tipos + Macro executada + Nova verificação de tipos

Page 64: Scala 2.10.0

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

Page 65: Scala 2.10.0

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.

Page 66: Scala 2.10.0

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”

Page 67: Scala 2.10.0

SIP-16: MacrosType 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

Page 68: Scala 2.10.0

SIP-16: Macros// Macro annotations

@memoizedef 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

Page 69: Scala 2.10.0

SIP-16: MacrosSomente 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!

Page 70: Scala 2.10.0

SIP-16: MacrosVantagens de Typed Macros:

Relativamente simples de implementarAssinatura 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

Page 71: Scala 2.10.0

SIP-16: MacrosDesvantagens:

Limites no que é possívelCompilação em dois estágios

Não é possível compilar uma macro e usá-la em um único passo

Não-higienica por defaultQuem é do contra vai continuar achando ruim

Page 72: Scala 2.10.0

SIP-16: Macrosobject Trimmer { def trim(s: String): String = macro trimImpl

import scala.reflect.makro.Context def trimImpl(c: Context)(s: c.Expr[String]): c.Expr[String] = { import c.universe._ // see reflection

val Literal(Constant(untrimmed: String)) = s.tree val trimmed = untrimmed.lines.map(_.trim).mkString("\n")

c.Expr(Literal(Constant(trimmed))) }}

Page 73: Scala 2.10.0

SIP-16: MacrosTipos 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

Page 74: Scala 2.10.0

SIP-17: Tipo DynamicProblema: a integração de Scala com outras

linguagens assume tipagem estáticaGrande quantidade de alternativas dinâmicas

na JVM!Solução: trait DynamicSimilar ao “missing method”Facilita integração com linguagens dinâmicas

na JVMMas tem outras utilidades...

Page 75: Scala 2.10.0

SIP-17: Tipo Dynamicscala> 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>).bres9: scala.xml.NodeSeq = NodeSeq(<b><c/></b>)

Page 76: Scala 2.10.0

SIP-17: Tipo DynamicConversões:

Métodos convencionais:applyDynamic

Métodos com nome de parâmetros:applyDynamicNamed

Atribuições (setters):updateDynamic

Valores (getters):selectDynamic

Page 77: Scala 2.10.0

Problemas:Algumas funcionalidades de Scala são de difícil

compreensãoOutras induzem a errosE 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

Page 78: Scala 2.10.0

Controla acesso a certas funcionalidadesUso das funcionalidades causa avisos

Mas podem se tornar erros em futuras versõesLiberação de uso através de:

flag de compilaçãovalor implícito no escopo

Liberação pode ser herdadaScalaDoc explica prós e contras de cada

funcionalidade

SIP-18: Modularização de Funcionalidades da Linguagem

Page 79: Scala 2.10.0

Funcionalidades contenciosasOperadores pós-fixadosChamada de métodos implementadas via reflexãoConversões de tipo implícitasHigher kinded typesExistenciais

Exceto aqueles que equivalem a Java wildcard typesTipo Dynamic

Funcionalidades experimentaisMacros

SIP-18: Modularização de Funcionalidades da Linguagem

Page 80: Scala 2.10.0

SIP-18: Modularização de Funcionalidades da Linguagem// Notação de operador pós-fixado

scala> "abc" lengthwarning: there were 1 feature warnings; re-run with -feature for detailsres0: Int = 3

Page 81: Scala 2.10.0

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 enabledby 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 discussionwhy the feature should be explicitly enabled. "abc" length ^res0: Int = 3

Page 82: Scala 2.10.0

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 enabledby 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 discussionwhy the feature should be explicitly enabled. x.hello ^world

Page 83: Scala 2.10.0

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 enabledby 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 discussionwhy the feature should be explicitly enabled. implicit def f(s: String): Int = Predef.augmentString(s).toInt ^f: (s: String)Int

Page 84: Scala 2.10.0

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

SIP-18: Modularização de Funcionalidades da Linguagem

Page 85: Scala 2.10.0

SIP-18: Modularização de Funcionalidades da Linguagem// Higher Kinded Types

scala> class Monad[M[_]]<console>:9: warning: higher-kinded type should be enabledby 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 discussionwhy the feature should be explicitly enabled. class Monad[M[_]] ^defined class Monad

Page 86: Scala 2.10.0

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 enabledby 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 discussionwhy the feature should be explicitly enabled. val l: List[ T forSome { type T }] = List(1) ^l: List[T forSome { type T }] = List(1)

Page 87: Scala 2.10.0

SIP-18: Modularização de Funcionalidades da Linguagem// Tipo Dynamic

TODO

Page 88: Scala 2.10.0

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 enabledby 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 discussionwhy the feature needs to be explicitly enabled. def g(d: Any): Any = macro f ^

Page 89: Scala 2.10.0

scala.reflectPermitem explorar a estrutura de um

programa,e interagir com esta estrutura

Wiki: reflexão ocorre em tempo de execuçãoScala: você usa a mesma biblioteca em tempo

de compilação, com macrosNoções fundamentais:

Bibliotecas de reflexão e UniversosNomes, símbolos, tipos, árvoresMirrors

Page 90: Scala 2.10.0

scala.reflect – Universos

Fonte: Scala Reflection Pre-SIP

Page 91: Scala 2.10.0

scala.reflect – UniversosContém uma série de elementos interligados

que, juntos, formam os componentes fundamentais da reflexãoSymbolTreeNameetc...

Uso de path dependent types para associar tipos aos universos dos quais se originaram

Page 92: Scala 2.10.0

scala.reflect – UniversosConstruí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 ScalaMakro

Manipulação em tempo de compilação Universo do compilador, mas com uma API mais restrita

Outros: Compilador

Page 93: Scala 2.10.0

scala.reflect – Tipos Fundamentais

Universo

Name

Symbol

Type

Tree

Position

AnnotationInfo

FlagSet

Page 94: Scala 2.10.0

scala.reflect – Name

Name

TermName

TypeName

Page 95: Scala 2.10.0

scala.reflect – NameScala possui dois espaços de nome:

TiposValores (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

Page 96: Scala 2.10.0

scala.reflect – Symbol

Symbol

Type

Symbol Type ...

owner

Symbol

Name

TermName

TypeName

Page 97: Scala 2.10.0

scala.reflect – SymbolTodas definições estão associadas a símbolos

ClassesMétodosParâmetrosVariáveisSe você deu um nome, tem um símboloSe você não deu um nome, mas chama de

“anônimo”, tem um símbolo tambémMutável no compilador, imutável em tempo

de execução

Page 98: Scala 2.10.0

scala.reflect – TypeRepresenta a estrutura associada a um tipo:

Membros das classesParâmetros e tipo de retorno de um métodoetc

Formado por case classes imutáveisManipulado através de pattern matching

Page 99: Scala 2.10.0

scala.reflect – Tipos e Símbolosscala> 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.typeSignatureres2: reflect.runtime.universe.Type = => A

scala> res1.typeSignatureIn(res0)res3: reflect.runtime.universe.Type = => Int

Page 100: Scala 2.10.0

scala.reflect – Tipos e Símbolosdef 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 }}

Page 101: Scala 2.10.0

scala.reflect – Tipos e Símbolosdef 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 }}

Page 102: Scala 2.10.0

scala.reflect – Tipos e Símbolos// Na verdade, você precisa disso:

case (m, mt @ NullaryMethodType(tpe)) if tpe =:= IntType =>

Page 103: Scala 2.10.0

scala.reflect – Tree

Tree

children

Tree Tree ... Tree

Type Position

Symbol

TypTree TermTree

Page 104: Scala 2.10.0

scala.reflect – TreeSão a representação interna do compilador

do código fonteImutável, formado por case classesEssencial ao se lidar com macrosUsado para annotated typed na biblioteca

básica

Page 105: Scala 2.10.0

scala.reflect – Treescala> import scala.tools.reflect.ToolBoximport 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)

Page 106: Scala 2.10.0

scala.reflect – Treescala> import scala.reflect.runtime.universe._import scala.reflect.runtime.universe._

scala> showRaw(reify({ def f(x: Int, y: Int) = x + y }).tree)res4: String = Block(List(DefDef(Modifiers(), newTermName("f"), List(), List(List(ValDef(Modifiers(PARAM), newTermName("x"), Ident(scala.Int), EmptyTree), ValDef(Modifiers(PARAM), newTermName("y"), Ident(scala.Int), EmptyTree))), TypeTree(), Apply(Select(Ident(newTermName("x")), newTermName("$plus")), List(Ident(newTermName("y")))))), Literal(Constant(())))

Page 107: Scala 2.10.0

scala.reflect – Mirror

InstanceMirror

ClassMirror FieldMirror MethodMirror

ModuleMirror

ClassMirror

MethodMirror

(constructors)

Page 108: Scala 2.10.0

scala.reflect – MirrorMirrors permitem manipulação de instâncias

e classes em tempo de execuçãoCada Universe pode ter um ou mais mirrorsCada mirror está associado a um class loaderClasses de mesmo nome podem existir

carregadas por class loaders distintosMirrors permitem manipulação baseada na

linguagem Scala, e não em sua implementação na JVM

Page 109: Scala 2.10.0

scala.reflect – Mirrorval obj = "String"val objClass = obj.getClassval classClassLoader = objClass.getClassLoaderval classLoaderMirror = runtimeMirror(classClassLoader)val classSymbol = classLoaderMirror.classSymbol(objClass)val classType = classSymbol.typeSignatureval methodName = newTermName("length")val methodSymbol = classType.member(methodName).asMethodSymbolval instanceMirror = classLoaderMirror.reflect(obj)val methodMirror = instanceMirror.reflectMethod(methodSymbol)methodMirror.apply() // == (obj.length: Any)

Page 110: Scala 2.10.0

Atores e Akka???A biblioteca padrão deixará de existir

Substituída pelo AkkaQuando???

A biblioteca Akka fará parte da distribuição 2.10Somente binários – código fonte permanece

separadoSerá disponibilizado um guia de migraçãoA biblioteca padrão virá com um “kit” para

facilitar a migraçãoPara que serve?

Page 111: Scala 2.10.0

O futuro distante

Page 112: Scala 2.10.0

Especulaçõesuntyped macros

for { val x = 0; x < 10; x += 1 } println(x)

macro typesclass X extends MacroClassY(parm)

macro annotations@memoize def fat(n: Int) = if (n > 0) n * fat(n -1) else 1

effect systemintegração de abstract types e type parameters.pré-processador (DOA!)