SlideShare une entreprise Scribd logo
1  sur  24
Télécharger pour lire hors ligne
scala.reflect

Eugene Burmako

  EPFL, LAMP



 19 May 2012
Agenda


  Intro


  API


  Demo


  Summary
Reflection




   A way for a program to learn about itself.
   Who should we ask?
       OS
       JVM
       Compiler
Scala reflection




   Interface to the Scala compiler:
       Full-fledged (cf. scalap, Code.lift, manifests)
       Cross-stage (available both at compile-time and at runtime)
       Uniform (the same API – universes, mirrors, trees, symbols,
       types – is used everywhere)
Before we start

       This is a fantasy (yet, a blessed fantasy) API. It will be
       implemented only in M4 (i.e. released in 1-2 weeks).
       Reflection in M3 is quite similar to what we’ll be discussing
       today, except that runtime reflection is fundamentally broken.
       In the final release (and, possibly, in M4 as well) reflection will
       be factored out into scala-reflect.jar. It’s a new core jar in the
       Scala distribution (along with scala-library.jar and
       scala-compiler.jar), estimated size is 2-3 Mb.
       For the brave ones, proto-M4 reflection might be found at
       scalamacros/topic/reflection and at odersky/topic/reflection.
       Proceed with care, as virtually anything might blow up in your
       face. You’re welcome to bug me at eugene.burmako@epfl.ch.
Agenda


  Intro


  API


  Demo


  Summary
Entry point: runtime
   This is something well-known from Java or C#, a runtime
   reflection API. You know what I mean.
   > val ru = scala.reflect.runtime.universe
   ru: scala.reflect.runtime.Universe = ...

   > val mirror = ru.reflectClass(classOf[C])
   mirror: scala.reflect.runtime.Universe#ClassMirror = ...

   > val c = mirror.symbol
   c: scala.reflect.runtime.Universe#Symbol = ...

   > val m = c.typeSignature.member("x").suchThat(_.isMethod)
   m: scala.reflect.runtime.Universe#Symbol = ...


   Note the terminology: universes as umbrellas, mirrors as reflectors,
   symbols as reference points. It is shared across entry points.
Entry point: compile-time
   The beauty of our reflection API manifests itself in macros. The
   environment is different, yet, the interface is the same.
   class Queryable[T] {
     def map[U](p: T => U): Queryable[U] =
       macro QImpl.map[T, U]
   }

   object QImpl {
     def map[T: c.TypeTag, U: c.TypeTag]
           (c: scala.reflect.makro.Context)
           (p: c.Expr[T => U])
           : c.Expr[Queryable[U]] = ...
   }


   Context is an entry point to compile-time reflection. It exposes a
   universe (the compiler) and a mirror (the symbol table).
Entry point: compile-time


   The control is inversed here. At runtime you call the compiler. At
   compile-time the compiler calls you.
   Currently we support only one kind of compile-time hooks - macro
   definitions. You declare a method to be a macro def by writing its
   body in a special way, and then every invocation of that method
   will be compiled by calling into the corresponding macro
   implementation.
   We also plan to research macro types (typedefs that expand into
   generated types) and macro annotations (annotations that modify
   program elements - expressions, methods, types). Who knows
   what is going to be next =)
Entry point: cross-stage



   Compile-time and runtime parts of your program can play together
   to the mutual benefit.
   For example, you can save artifacts from the compile-time universe
   and pass them to the runtime. Makes sense - these artifacts are
   quite useful, but a lot of them are destroyed by compilation.
   This is called reification. With the unified reflection API, it is both
   possible, easy to implement and future-proof.
Reified types
   Scala 2.8 introduced manifests, a tool to persist type arguments in
   the presence of erasure. Manifests encode reified types in a series
   of factory calls.
   > implicitly[Manifest[List[String]]]
   ...
   Manifest.classType[List[String]](
     classOf[List],
     Manifest.classType[String](classOf[java.lang.String]))
   ...
   res0: Manifest[List[String]] =
       scala.collection.immutable.List[String]


   Usefulness of manifests is limited. They are doing fine as array
   creators, they can also express simple polymorphic types, but they
   totally bail on complex things such as compounds and existentials.
   The most reliable part of manifests is the toString method.
Reified types
   In Scala 2.10 type tags improve upon manifests. They are thin
   wrappers over compiler Types exposed in the reflection API.
   > implicitly[ru.TypeTag[List[String]]]
   ...
   materializing requested TypeTag[List[String]]
   using materializeTypeTag[List[String]](ru)
   ...
   $u.ConcreteTypeTag[List[String]]($u.TypeRef(
     $u.ThisType("scala.collection.immutable"),
     $m.staticClass("scala.collection.immutable.List"),
     List($m.staticClass("java.lang.String").asType)))
   ...
   res0: ru.TypeTag[List[String]] =
       ru.ConcreteTypeTag[List[String]]


   Having a type tag you can do (almost) whatever the compiler can
   do with a type, e.g. destructure it, create types from it, use it
   during compilation (yes, I’m talking runtime compilation).
Reified trees

   Scala 2.8 sneakily introduced code lifting, a tool to persist
   compiler trees. Trees produced by Code.lift are similar to compiler
   ASTs, yet their implementation is disparate.
   > Code.lift{ val y = x + 2 }
   Code[Unit](ValDef(
     LocalValue(reflect.this.NoSymbol, "y", NoType),
     Apply(
       Select(Literal(x), Method("scala.Int.$plus"), ...),
       List(Literal(2))))))


   As a result, lifted trees only expose a small subset of operations
   that can be done on compiler trees. For example, they are typed,
   yet they cannot be typechecked, they have symbols, but those
   cannot be fully inspected and so on.
Reified trees
   In Scala 2.10 we have the reify macro that takes a Scala snippet
   (an expression, a declaration, a bunch of declarations) and
   reproduces it at runtime.
   > ru.reify{ val y = x + 2 }
   val free$x1: $u.Symbol =
     $u.build.newFreeTerm("x", $m.staticClass("Int"), x)
   $u.Expr[Unit]($u.ValDef(
       $u.NoMods,
       $u.newTermName("y"),
       $u.TypeTree(),
       $u.Apply(
         $u.Select($u.Ident(free$x1), "$plus"),
         List($u.Literal($u.Constant(2))))))


   Reify uses compiler trees to persist the ASTs. As of such, reified
   trees can be typechecked, compiled, can serve as templates for
   other trees, etc.
Agenda


  Intro


  API


  Demo


  Summary
Inspect members

   scala> trait X { def foo: String }
   defined trait X

   scala> ru.typeTag[X]
   res1: ru.TypeTag[X] = ru.ConcreteTypeTag[X]

   scala> res1.tpe.members
   res2: Iterable[ru.Symbol] = List(method $asInstanceOf,
       method $isInstanceOf, method synchronized, method ##,
       method !=, method ==, method ne, method eq,
       constructor Object, method notifyAll, method notify,
       method clone, method getClass, method hashCode,
       method toString, method equals, method wait, method
       wait, method wait, method finalize, method
       asInstanceOf, method isInstanceOf, method !=, method
       ==, method foo)
Analyze, typecheck and invoke members

   val d = new DynamicProxy{ val dynamicProxyTarget = x }
   d.noargs
   d.noargs()
   d.nullary
   d.value
   d.-
   d.$("x")
   d.overloaded("overloaded")
   d.overloaded(1)
   val car = new Car
   d.typeArgs(car) // inferred
   d.default(1, 3)
   d.default(1)
   d.named(1, c=3, b=2) // works, wow
Defeat erasure
   scala> def foo[T](x: T) = x.getClass
   foo: [T](x: T)Class[_ <: T]

   scala> foo(List(1, 2, 3))
   res0: Class[_ <: List[Int]] = class
       scala.collection.immutable.$colon$colon

   scala> def foo[T: ru.TypeTag](x: T) = ru.typeTag[T]
   foo: [T](x: T)(implicit evidence$1:
       ru.TypeTag[T])ru.TypeTag[T]

   scala> foo(List(1, 2, 3))
   res1: ru.TypeTag[List[Int]] =
       ru.ConcreteTypeTag[List[Int]]

   scala> res1.tpe
   res2: ru.Type = List[Int]
Compile at runtime


   import ru._
   val tree = Apply(Select(Ident("Macros"),
       newTermName("foo")), List(Literal(Constant(42))))
   println(Expr(tree).eval)


   Eval creates a toolbox under the covers (universe.mkToolBox),
   which is a full-fledged compiler.
   Toolbox wraps the input AST, sets its phase to Namer (skipping
   Parser) and performs the compilation into an in-memory
   directory.
   After the compilation is finished, toolbox fires up a classloader that
   loads and lauches the code.
Compile at compile-time

   object Asserts {
     def assertionsEnabled = ...
     def raise(msg: Any) = throw new AssertionError(msg)
     def assertImpl(c: scala.reflect.makro.Context)
       (cond: c.Expr[Boolean], msg: c.Expr[Any])
       : c.Expr[Unit] =
     if (assertionsEnabled)
       c.reify(if (!cond.eval) raise(msg.eval))
     else
       c.reify(())
   }


   Also known as macros. Can be used for a multitude of real-world
   use-cases: advanced DSLs, language-integrated queries, type
   providers, integration of externals DSLs with string interpolation,
   your fancy macro hackery could also be mentioned here.
Agenda


  Intro


  API


  Demo


  Summary
Summary




     In 2.10 you can have all the information about your program
     that the compiler has (well, almost).
     This information includes trees, symbols and types. And
     annotations. And positions. And more.
     You can reflect at runtime (scala.reflect.runtime.universe) or
     at compile-time (macros).
Status




   Recently released 2.10.0-M3 includes reflection and macros.
   Compile-time reflection in M3 works well, and we’ve already
   improved the compiler with it.
   Runtime reflection in M3 is broken beyond repair, so we have
   rewritten it. This will show up in M4 (i.e. in 1-2 weeks).
Thanks!




          eugene.burmako@epfl.ch

Contenu connexe

Tendances

A Sceptical Guide to Functional Programming
A Sceptical Guide to Functional ProgrammingA Sceptical Guide to Functional Programming
A Sceptical Guide to Functional Programming
Garth Gilmour
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
pramode_ce
 
Functional Objects & Function and Closures
Functional Objects  & Function and ClosuresFunctional Objects  & Function and Closures
Functional Objects & Function and Closures
Sandip Kumar
 

Tendances (19)

Joy of scala
Joy of scalaJoy of scala
Joy of scala
 
Scala fundamentals
Scala fundamentalsScala fundamentals
Scala fundamentals
 
Kotlin in action
Kotlin in actionKotlin in action
Kotlin in action
 
Scala - brief intro
Scala - brief introScala - brief intro
Scala - brief intro
 
Workshop Scala
Workshop ScalaWorkshop Scala
Workshop Scala
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
A Sceptical Guide to Functional Programming
A Sceptical Guide to Functional ProgrammingA Sceptical Guide to Functional Programming
A Sceptical Guide to Functional Programming
 
Kotlin
KotlinKotlin
Kotlin
 
A Tour Of Scala
A Tour Of ScalaA Tour Of Scala
A Tour Of Scala
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
 
Scaladroids: Developing Android Apps with Scala
Scaladroids: Developing Android Apps with ScalaScaladroids: Developing Android Apps with Scala
Scaladroids: Developing Android Apps with Scala
 
Scala
ScalaScala
Scala
 
Scala vs Ruby
Scala vs RubyScala vs Ruby
Scala vs Ruby
 
Kotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRreadyKotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRready
 
Scala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldScala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 World
 
Scala on Android
Scala on AndroidScala on Android
Scala on Android
 
Kotlin, smarter development for the jvm
Kotlin, smarter development for the jvmKotlin, smarter development for the jvm
Kotlin, smarter development for the jvm
 
Functional Objects & Function and Closures
Functional Objects  & Function and ClosuresFunctional Objects  & Function and Closures
Functional Objects & Function and Closures
 
Kotlin hands on - MorningTech ekito 2017
Kotlin hands on - MorningTech ekito 2017Kotlin hands on - MorningTech ekito 2017
Kotlin hands on - MorningTech ekito 2017
 

En vedette

Zhitarev vsyo chto_vy_hoteli_znat_o_maestro
Zhitarev vsyo chto_vy_hoteli_znat_o_maestroZhitarev vsyo chto_vy_hoteli_znat_o_maestro
Zhitarev vsyo chto_vy_hoteli_znat_o_maestro
drupalconf
 
Kostin drupal conf-2011-winter
Kostin drupal conf-2011-winterKostin drupal conf-2011-winter
Kostin drupal conf-2011-winter
drupalconf
 
Komelin drupalconf report_komelin_v2
Komelin drupalconf report_komelin_v2Komelin drupalconf report_komelin_v2
Komelin drupalconf report_komelin_v2
drupalconf
 
опыт использования схемы Drupal+varnish+nginx руслан исай
опыт использования схемы Drupal+varnish+nginx руслан исайопыт использования схемы Drupal+varnish+nginx руслан исай
опыт использования схемы Drupal+varnish+nginx руслан исай
drupalconf
 
инструкция по оптимизации сайтов на Drupal херени даниэл
инструкция по оптимизации сайтов на Drupal херени даниэлинструкция по оптимизации сайтов на Drupal херени даниэл
инструкция по оптимизации сайтов на Drupal херени даниэл
drupalconf
 
Fotostock on drupal zhitarev anton (eng)
Fotostock on drupal zhitarev anton (eng)Fotostock on drupal zhitarev anton (eng)
Fotostock on drupal zhitarev anton (eng)
drupalconf
 

En vedette (8)

Azure
AzureAzure
Azure
 
Zhitarev vsyo chto_vy_hoteli_znat_o_maestro
Zhitarev vsyo chto_vy_hoteli_znat_o_maestroZhitarev vsyo chto_vy_hoteli_znat_o_maestro
Zhitarev vsyo chto_vy_hoteli_znat_o_maestro
 
Kostin drupal conf-2011-winter
Kostin drupal conf-2011-winterKostin drupal conf-2011-winter
Kostin drupal conf-2011-winter
 
Komelin drupalconf report_komelin_v2
Komelin drupalconf report_komelin_v2Komelin drupalconf report_komelin_v2
Komelin drupalconf report_komelin_v2
 
Василий Ременюк «Курс молодого подрывника»
Василий Ременюк «Курс молодого подрывника» Василий Ременюк «Курс молодого подрывника»
Василий Ременюк «Курс молодого подрывника»
 
опыт использования схемы Drupal+varnish+nginx руслан исай
опыт использования схемы Drupal+varnish+nginx руслан исайопыт использования схемы Drupal+varnish+nginx руслан исай
опыт использования схемы Drupal+varnish+nginx руслан исай
 
инструкция по оптимизации сайтов на Drupal херени даниэл
инструкция по оптимизации сайтов на Drupal херени даниэлинструкция по оптимизации сайтов на Drupal херени даниэл
инструкция по оптимизации сайтов на Drupal херени даниэл
 
Fotostock on drupal zhitarev anton (eng)
Fotostock on drupal zhitarev anton (eng)Fotostock on drupal zhitarev anton (eng)
Fotostock on drupal zhitarev anton (eng)
 

Similaire à Евгений Бурмако «scala.reflect»

scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdf
Hiroshi Ono
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdf
Hiroshi Ono
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdf
Hiroshi Ono
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdf
Hiroshi Ono
 
Task Perform addition subtraction division and multiplic.pdf
Task Perform addition subtraction division and multiplic.pdfTask Perform addition subtraction division and multiplic.pdf
Task Perform addition subtraction division and multiplic.pdf
acsmadurai
 
Learn a language : LISP
Learn a language : LISPLearn a language : LISP
Learn a language : LISP
Devnology
 
Martin Odersky - Evolution of Scala
Martin Odersky - Evolution of ScalaMartin Odersky - Evolution of Scala
Martin Odersky - Evolution of Scala
Scala Italy
 

Similaire à Евгений Бурмако «scala.reflect» (20)

Metaprogramming in Scala 2.10, Eugene Burmako,
Metaprogramming  in Scala 2.10, Eugene Burmako, Metaprogramming  in Scala 2.10, Eugene Burmako,
Metaprogramming in Scala 2.10, Eugene Burmako,
 
Scala Reflection & Runtime MetaProgramming
Scala Reflection & Runtime MetaProgrammingScala Reflection & Runtime MetaProgramming
Scala Reflection & Runtime MetaProgramming
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdf
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdf
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdf
 
scalaliftoff2009.pdf
scalaliftoff2009.pdfscalaliftoff2009.pdf
scalaliftoff2009.pdf
 
Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009Scala Talk at FOSDEM 2009
Scala Talk at FOSDEM 2009
 
Fuel Up JavaScript with Functional Programming
Fuel Up JavaScript with Functional ProgrammingFuel Up JavaScript with Functional Programming
Fuel Up JavaScript with Functional Programming
 
scalar.pdf
scalar.pdfscalar.pdf
scalar.pdf
 
Practical cats
Practical catsPractical cats
Practical cats
 
Stata Programming Cheat Sheet
Stata Programming Cheat SheetStata Programming Cheat Sheet
Stata Programming Cheat Sheet
 
Google06
Google06Google06
Google06
 
Task Perform addition subtraction division and multiplic.pdf
Task Perform addition subtraction division and multiplic.pdfTask Perform addition subtraction division and multiplic.pdf
Task Perform addition subtraction division and multiplic.pdf
 
Stata cheatsheet programming
Stata cheatsheet programmingStata cheatsheet programming
Stata cheatsheet programming
 
2014 holden - databricks umd scala crash course
2014   holden - databricks umd scala crash course2014   holden - databricks umd scala crash course
2014 holden - databricks umd scala crash course
 
Scala tutorial
Scala tutorialScala tutorial
Scala tutorial
 
Scala tutorial
Scala tutorialScala tutorial
Scala tutorial
 
Stepping Up : A Brief Intro to Scala
Stepping Up : A Brief Intro to ScalaStepping Up : A Brief Intro to Scala
Stepping Up : A Brief Intro to Scala
 
Learn a language : LISP
Learn a language : LISPLearn a language : LISP
Learn a language : LISP
 
Martin Odersky - Evolution of Scala
Martin Odersky - Evolution of ScalaMartin Odersky - Evolution of Scala
Martin Odersky - Evolution of Scala
 

Plus de e-Legion

Plus de e-Legion (20)

MBLT16: Elena Rydkina, Pure
MBLT16: Elena Rydkina, PureMBLT16: Elena Rydkina, Pure
MBLT16: Elena Rydkina, Pure
 
MBLT16: Alexander Lukin, AppMetrica
MBLT16: Alexander Lukin, AppMetricaMBLT16: Alexander Lukin, AppMetrica
MBLT16: Alexander Lukin, AppMetrica
 
MBLT16: Vincent Wu, Alibaba Mobile
MBLT16: Vincent Wu, Alibaba MobileMBLT16: Vincent Wu, Alibaba Mobile
MBLT16: Vincent Wu, Alibaba Mobile
 
MBLT16: Dmitriy Geranin, Afisha Restorany
MBLT16: Dmitriy Geranin, Afisha RestoranyMBLT16: Dmitriy Geranin, Afisha Restorany
MBLT16: Dmitriy Geranin, Afisha Restorany
 
MBLT16: Marvin Liao, 500Startups
MBLT16: Marvin Liao, 500StartupsMBLT16: Marvin Liao, 500Startups
MBLT16: Marvin Liao, 500Startups
 
MBLT16: Andrey Maslak, Aviasales
MBLT16: Andrey Maslak, AviasalesMBLT16: Andrey Maslak, Aviasales
MBLT16: Andrey Maslak, Aviasales
 
MBLT16: Andrey Bakalenko, Sberbank Online
MBLT16: Andrey Bakalenko, Sberbank OnlineMBLT16: Andrey Bakalenko, Sberbank Online
MBLT16: Andrey Bakalenko, Sberbank Online
 
Rx Java architecture
Rx Java architectureRx Java architecture
Rx Java architecture
 
Rx java
Rx javaRx java
Rx java
 
MBLTDev15: Hector Zarate, Spotify
MBLTDev15: Hector Zarate, SpotifyMBLTDev15: Hector Zarate, Spotify
MBLTDev15: Hector Zarate, Spotify
 
MBLTDev15: Cesar Valiente, Wunderlist
MBLTDev15: Cesar Valiente, WunderlistMBLTDev15: Cesar Valiente, Wunderlist
MBLTDev15: Cesar Valiente, Wunderlist
 
MBLTDev15: Brigit Lyons, Soundcloud
MBLTDev15: Brigit Lyons, SoundcloudMBLTDev15: Brigit Lyons, Soundcloud
MBLTDev15: Brigit Lyons, Soundcloud
 
MBLTDev15: Egor Tolstoy, Rambler&Co
MBLTDev15: Egor Tolstoy, Rambler&CoMBLTDev15: Egor Tolstoy, Rambler&Co
MBLTDev15: Egor Tolstoy, Rambler&Co
 
MBLTDev15: Alexander Orlov, Postforpost
MBLTDev15: Alexander Orlov, PostforpostMBLTDev15: Alexander Orlov, Postforpost
MBLTDev15: Alexander Orlov, Postforpost
 
MBLTDev15: Artemiy Sobolev, Parallels
MBLTDev15: Artemiy Sobolev, ParallelsMBLTDev15: Artemiy Sobolev, Parallels
MBLTDev15: Artemiy Sobolev, Parallels
 
MBLTDev15: Alexander Dimchenko, DIT
MBLTDev15: Alexander Dimchenko, DITMBLTDev15: Alexander Dimchenko, DIT
MBLTDev15: Alexander Dimchenko, DIT
 
MBLTDev: Evgeny Lisovsky, Litres
MBLTDev: Evgeny Lisovsky, LitresMBLTDev: Evgeny Lisovsky, Litres
MBLTDev: Evgeny Lisovsky, Litres
 
MBLTDev: Alexander Dimchenko, Bright Box
MBLTDev: Alexander Dimchenko, Bright Box MBLTDev: Alexander Dimchenko, Bright Box
MBLTDev: Alexander Dimchenko, Bright Box
 
MBLTDev15: Konstantin Goldshtein, Microsoft
MBLTDev15: Konstantin Goldshtein, MicrosoftMBLTDev15: Konstantin Goldshtein, Microsoft
MBLTDev15: Konstantin Goldshtein, Microsoft
 
MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank
MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank
MBLTDev15: Anna Mikhina, Maxim Evdokimov, Tinkoff Bank
 

Dernier

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Dernier (20)

ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu SubbuApidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
A Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source MilvusA Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source Milvus
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 

Евгений Бурмако «scala.reflect»

  • 1. scala.reflect Eugene Burmako EPFL, LAMP 19 May 2012
  • 2. Agenda Intro API Demo Summary
  • 3. Reflection A way for a program to learn about itself. Who should we ask? OS JVM Compiler
  • 4. Scala reflection Interface to the Scala compiler: Full-fledged (cf. scalap, Code.lift, manifests) Cross-stage (available both at compile-time and at runtime) Uniform (the same API – universes, mirrors, trees, symbols, types – is used everywhere)
  • 5. Before we start This is a fantasy (yet, a blessed fantasy) API. It will be implemented only in M4 (i.e. released in 1-2 weeks). Reflection in M3 is quite similar to what we’ll be discussing today, except that runtime reflection is fundamentally broken. In the final release (and, possibly, in M4 as well) reflection will be factored out into scala-reflect.jar. It’s a new core jar in the Scala distribution (along with scala-library.jar and scala-compiler.jar), estimated size is 2-3 Mb. For the brave ones, proto-M4 reflection might be found at scalamacros/topic/reflection and at odersky/topic/reflection. Proceed with care, as virtually anything might blow up in your face. You’re welcome to bug me at eugene.burmako@epfl.ch.
  • 6. Agenda Intro API Demo Summary
  • 7. Entry point: runtime This is something well-known from Java or C#, a runtime reflection API. You know what I mean. > val ru = scala.reflect.runtime.universe ru: scala.reflect.runtime.Universe = ... > val mirror = ru.reflectClass(classOf[C]) mirror: scala.reflect.runtime.Universe#ClassMirror = ... > val c = mirror.symbol c: scala.reflect.runtime.Universe#Symbol = ... > val m = c.typeSignature.member("x").suchThat(_.isMethod) m: scala.reflect.runtime.Universe#Symbol = ... Note the terminology: universes as umbrellas, mirrors as reflectors, symbols as reference points. It is shared across entry points.
  • 8. Entry point: compile-time The beauty of our reflection API manifests itself in macros. The environment is different, yet, the interface is the same. class Queryable[T] { def map[U](p: T => U): Queryable[U] = macro QImpl.map[T, U] } object QImpl { def map[T: c.TypeTag, U: c.TypeTag] (c: scala.reflect.makro.Context) (p: c.Expr[T => U]) : c.Expr[Queryable[U]] = ... } Context is an entry point to compile-time reflection. It exposes a universe (the compiler) and a mirror (the symbol table).
  • 9. Entry point: compile-time The control is inversed here. At runtime you call the compiler. At compile-time the compiler calls you. Currently we support only one kind of compile-time hooks - macro definitions. You declare a method to be a macro def by writing its body in a special way, and then every invocation of that method will be compiled by calling into the corresponding macro implementation. We also plan to research macro types (typedefs that expand into generated types) and macro annotations (annotations that modify program elements - expressions, methods, types). Who knows what is going to be next =)
  • 10. Entry point: cross-stage Compile-time and runtime parts of your program can play together to the mutual benefit. For example, you can save artifacts from the compile-time universe and pass them to the runtime. Makes sense - these artifacts are quite useful, but a lot of them are destroyed by compilation. This is called reification. With the unified reflection API, it is both possible, easy to implement and future-proof.
  • 11. Reified types Scala 2.8 introduced manifests, a tool to persist type arguments in the presence of erasure. Manifests encode reified types in a series of factory calls. > implicitly[Manifest[List[String]]] ... Manifest.classType[List[String]]( classOf[List], Manifest.classType[String](classOf[java.lang.String])) ... res0: Manifest[List[String]] = scala.collection.immutable.List[String] Usefulness of manifests is limited. They are doing fine as array creators, they can also express simple polymorphic types, but they totally bail on complex things such as compounds and existentials. The most reliable part of manifests is the toString method.
  • 12. Reified types In Scala 2.10 type tags improve upon manifests. They are thin wrappers over compiler Types exposed in the reflection API. > implicitly[ru.TypeTag[List[String]]] ... materializing requested TypeTag[List[String]] using materializeTypeTag[List[String]](ru) ... $u.ConcreteTypeTag[List[String]]($u.TypeRef( $u.ThisType("scala.collection.immutable"), $m.staticClass("scala.collection.immutable.List"), List($m.staticClass("java.lang.String").asType))) ... res0: ru.TypeTag[List[String]] = ru.ConcreteTypeTag[List[String]] Having a type tag you can do (almost) whatever the compiler can do with a type, e.g. destructure it, create types from it, use it during compilation (yes, I’m talking runtime compilation).
  • 13. Reified trees Scala 2.8 sneakily introduced code lifting, a tool to persist compiler trees. Trees produced by Code.lift are similar to compiler ASTs, yet their implementation is disparate. > Code.lift{ val y = x + 2 } Code[Unit](ValDef( LocalValue(reflect.this.NoSymbol, "y", NoType), Apply( Select(Literal(x), Method("scala.Int.$plus"), ...), List(Literal(2)))))) As a result, lifted trees only expose a small subset of operations that can be done on compiler trees. For example, they are typed, yet they cannot be typechecked, they have symbols, but those cannot be fully inspected and so on.
  • 14. Reified trees In Scala 2.10 we have the reify macro that takes a Scala snippet (an expression, a declaration, a bunch of declarations) and reproduces it at runtime. > ru.reify{ val y = x + 2 } val free$x1: $u.Symbol = $u.build.newFreeTerm("x", $m.staticClass("Int"), x) $u.Expr[Unit]($u.ValDef( $u.NoMods, $u.newTermName("y"), $u.TypeTree(), $u.Apply( $u.Select($u.Ident(free$x1), "$plus"), List($u.Literal($u.Constant(2)))))) Reify uses compiler trees to persist the ASTs. As of such, reified trees can be typechecked, compiled, can serve as templates for other trees, etc.
  • 15. Agenda Intro API Demo Summary
  • 16. Inspect members scala> trait X { def foo: String } defined trait X scala> ru.typeTag[X] res1: ru.TypeTag[X] = ru.ConcreteTypeTag[X] scala> res1.tpe.members res2: Iterable[ru.Symbol] = List(method $asInstanceOf, method $isInstanceOf, method synchronized, method ##, method !=, method ==, method ne, method eq, constructor Object, method notifyAll, method notify, method clone, method getClass, method hashCode, method toString, method equals, method wait, method wait, method wait, method finalize, method asInstanceOf, method isInstanceOf, method !=, method ==, method foo)
  • 17. Analyze, typecheck and invoke members val d = new DynamicProxy{ val dynamicProxyTarget = x } d.noargs d.noargs() d.nullary d.value d.- d.$("x") d.overloaded("overloaded") d.overloaded(1) val car = new Car d.typeArgs(car) // inferred d.default(1, 3) d.default(1) d.named(1, c=3, b=2) // works, wow
  • 18. Defeat erasure scala> def foo[T](x: T) = x.getClass foo: [T](x: T)Class[_ <: T] scala> foo(List(1, 2, 3)) res0: Class[_ <: List[Int]] = class scala.collection.immutable.$colon$colon scala> def foo[T: ru.TypeTag](x: T) = ru.typeTag[T] foo: [T](x: T)(implicit evidence$1: ru.TypeTag[T])ru.TypeTag[T] scala> foo(List(1, 2, 3)) res1: ru.TypeTag[List[Int]] = ru.ConcreteTypeTag[List[Int]] scala> res1.tpe res2: ru.Type = List[Int]
  • 19. Compile at runtime import ru._ val tree = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant(42)))) println(Expr(tree).eval) Eval creates a toolbox under the covers (universe.mkToolBox), which is a full-fledged compiler. Toolbox wraps the input AST, sets its phase to Namer (skipping Parser) and performs the compilation into an in-memory directory. After the compilation is finished, toolbox fires up a classloader that loads and lauches the code.
  • 20. Compile at compile-time object Asserts { def assertionsEnabled = ... def raise(msg: Any) = throw new AssertionError(msg) def assertImpl(c: scala.reflect.makro.Context) (cond: c.Expr[Boolean], msg: c.Expr[Any]) : c.Expr[Unit] = if (assertionsEnabled) c.reify(if (!cond.eval) raise(msg.eval)) else c.reify(()) } Also known as macros. Can be used for a multitude of real-world use-cases: advanced DSLs, language-integrated queries, type providers, integration of externals DSLs with string interpolation, your fancy macro hackery could also be mentioned here.
  • 21. Agenda Intro API Demo Summary
  • 22. Summary In 2.10 you can have all the information about your program that the compiler has (well, almost). This information includes trees, symbols and types. And annotations. And positions. And more. You can reflect at runtime (scala.reflect.runtime.universe) or at compile-time (macros).
  • 23. Status Recently released 2.10.0-M3 includes reflection and macros. Compile-time reflection in M3 works well, and we’ve already improved the compiler with it. Runtime reflection in M3 is broken beyond repair, so we have rewritten it. This will show up in M4 (i.e. in 1-2 weeks).
  • 24. Thanks! eugene.burmako@epfl.ch