SlideShare une entreprise Scribd logo
1  sur  113
What’s new in
Groovy 2.0
  Guillaume Laforge
  Groovy Project Manager
  SpringSource / VMware
       @glaforge




                           1
Guillaume Laforge
 •   Groovy Project Manager at VMware
     •Initiator of the Grails framework
     •Creator of the Gaelyk

 •   Co-author of Groovy in Action


 •   Follow me on...
     •My blog: http://glaforge.appspot.com
     •Twitter: @glaforge
     •Google+: http://gplus.to/glaforge

                                             2
Agenda (1/2)
 • What’s in Groovy 1.8?
  • Nicer DSLs with command chains
  • Runtime performance improvements
  • GPars bundled for taming your multicores
  • Closure enhancements
  • Builtin JSON support
  • New AST transformations


                                               3
Agenda (2/2)
 • What’s new in Groovy 2.0?
  • Alignments with JDK 7
   • Project Coin (small language changes)
   • Invoke Dynamic support
    • Continued runtime performance improvements
  • Static type checking
  • Static compilation
  • Modularity

                                                   4
Command chains
 •   A grammar improvement allowing you
     to drop dots & parens
     when chaining method calls
     • an extended version of top-level statements like println


 •   Less dots, less parens allow you to
     •write more readable business rules
     •in almost plain English sentences
         •
        (or any language, of course)



                                                                  5
Command chains



     pull request on github




                              6
Command chains
      Alternation of
      method names




     pull request on github




                              6
Command chains
      Alternation of
      method names




     pull request on github


                   and parameters
                 (even named ones)




                                     6
Command chains



     pull request on github




                              6
Command chains


      Equivalent to:


     pull request on github
       (     ). (  )




                              6
Command chains




                 7
Command chains
   // methods with multiple arguments (commas)




                                                 7
Command chains
   // methods with multiple arguments (commas)
   take coffee  with sugar, milk  and liquor




                                                 7
Command chains
   // methods with multiple arguments (commas)
   take coffee  with sugar, milk  and liquor

   // leverage named-args as punctuation




                                                 7
Command chains
   // methods with multiple arguments (commas)
   take coffee  with sugar, milk  and liquor

   // leverage named-args as punctuation
   check that: margarita  tastes good




                                                 7
Command chains
   // methods with multiple arguments (commas)
   take coffee  with sugar, milk  and liquor

   // leverage named-args as punctuation
   check that: margarita  tastes good

   // closure parameters for new control structures




                                                      7
Command chains
   // methods with multiple arguments (commas)
   take coffee  with sugar, milk  and liquor

   // leverage named-args as punctuation
   check that: margarita  tastes good

   // closure parameters for new control structures
   given {}  when {}  then {}




                                                      7
Command chains
   // methods with multiple arguments (commas)
   take coffee  with sugar, milk  and liquor

   // leverage named-args as punctuation
   check that: margarita  tastes good

   // closure parameters for new control structures
   given {}  when {}  then {}

   // zero-arg methods require parens




                                                      7
Command chains
   // methods with multiple arguments (commas)
   take coffee  with sugar, milk  and liquor

   // leverage named-args as punctuation
   check that: margarita  tastes good

   // closure parameters for new control structures
   given {}  when {}  then {}

   // zero-arg methods require parens
   select all  unique() from names




                                                      7
Command chains
   // methods with multiple arguments (commas)
   take coffee  with sugar, milk  and liquor

   // leverage named-args as punctuation
   check that: margarita  tastes good

   // closure parameters for new control structures
   given {}  when {}  then {}

   // zero-arg methods require parens
   select all  unique() from names

   // possible with an odd number of terms




                                                      7
Command chains
   // methods with multiple arguments (commas)
   take coffee  with sugar, milk  and liquor

   // leverage named-args as punctuation
   check that: margarita  tastes good

   // closure parameters for new control structures
   given {}  when {}  then {}

   // zero-arg methods require parens
   select all  unique() from names

   // possible with an odd number of terms
   take 3  cookies




                                                      7
Command chains
   // methods with multiple arguments (commas)
   take coffee  with sugar, milk  and liquor
      (   ). (         ). (    )

   // leverage named-args as punctuation
   check that: margarita  tastes good

   // closure parameters for new control structures
   given {}  when {}  then {}

   // zero-arg methods require parens
   select all  unique() from names

   // possible with an odd number of terms
   take 3  cookies




                                                      7
Command chains
   // methods with multiple arguments (commas)
   take coffee  with sugar, milk  and liquor
      (   ). (         ). (    )

   // leverage named-args as punctuation
   check that: margarita  )tastes good
       (         ).  (

   // closure parameters for new control structures
   given {}  when {}  then {}

   // zero-arg methods require parens
   select all  unique() from names

   // possible with an odd number of terms
   take 3  cookies




                                                      7
Command chains
   // methods with multiple arguments (commas)
   take coffee  with sugar, milk  and liquor
      (   ). (         ). (    )

   // leverage named-args as punctuation
   check that: margarita  )tastes good
       (         ).  (

   // closure parameters for new control structures
   given). when {}  )
      ( {}  ( ). ( then {}

   // zero-arg methods require parens
   select all  unique() from names

   // possible with an odd number of terms
   take 3  cookies




                                                      7
Command chains
   // methods with multiple arguments (commas)
   take coffee  with sugar, milk  and liquor
      (   ). (         ). (    )

   // leverage named-args as punctuation
   check that: margarita  )tastes good
       (         ).  (

   // closure parameters for new control structures
   given). when {}  )
      ( {}  ( ). ( then {}

   // zero-arg methods require parens
   select all  unique() from names
       ( ).       . (     )

   // possible with an odd number of terms
   take 3  cookies




                                                      7
Command chains
   // methods with multiple arguments (commas)
   take coffee  with sugar, milk  and liquor
      (   ). (         ). (    )

   // leverage named-args as punctuation
   check that: margarita  )tastes good
       (         ).  (

   // closure parameters for new control structures
   given). when {}  )
      ( {}  ( ). ( then {}

   // zero-arg methods require parens
   select all  unique() from names
       ( ).       . (     )

   // possible with an odd number of terms
   take). cookies
      ( 3 




                                                      7
GPars bundled
 •   GPars is bundled in the Groovy distribution


 •   GPars covers a wide range of parallel
     and concurrent paradigms
     •actors, fork/join, map/filter/reduce, dataflow, agents
     •parallel arrays, executors, STM, and more...


 •   And you can use it from plain Java as well!


 •   http://gpars.codehaus.org/

                                                             8
Closure enhancements
 • Closure annotation parameters
 •    Some more functional flavor
     • composition
         •
         compose several closures into one single closure
     • trampoline
       • avoid stack overflow errors for recursive algorithms
     • memoization
       • remember the outcome of previous closure invocations
     • currying improvements

                                                            9
Closure annotation
     @Retention(RetentionPolicy.RUNTIME)
     @interface Invariant {    
        Class value() // a closure class
     }
      

 {   @Invariant({ number >= 0 })
     class Distance {    
        float number    
        String unit
     } 
      
     def d = new Distance(number: 10, unit: "meters") 
     def anno = Distance.getAnnotation(Invariant)
     def check = anno.value().newInstance(d, d)
     assert check(d)


                                                         10
Closure annotation
     @Retention(RetentionPolicy.RUNTIME)
     @interface Invariant {    
        Class value() // a closure class
     }
      

 {   @Invariant({ number >= 0 })
     class Distance {    
        float number                    Poor-m
                                              an’s GCont
                                                         racts

        String unit
     } 
      
     def d = new Distance(number: 10, unit: "meters") 
     def anno = Distance.getAnnotation(Invariant)
     def check = anno.value().newInstance(d, d)
     assert check(d)


                                                                 10
Closure memoization




                      11
Closure memoization
  def plus = { a, b -> sleep 1000; a + b }.memoize()




                                                       11
Closure memoization
  def plus = { a, b -> sleep 1000; a + b }.memoize()

  assert plus(1, 2) == 3 // after 1000ms




                                                       11
Closure memoization
  def plus = { a, b -> sleep 1000; a + b }.memoize()

  assert plus(1, 2) == 3 // after 1000ms
  assert plus(1, 2) == 3 // return immediately




                                                       11
Closure memoization
  def plus = { a, b -> sleep 1000; a + b }.memoize()

  assert plus(1, 2) == 3 // after 1000ms
  assert plus(1, 2) == 3 // return immediately
  assert plus(2, 2) == 4 // after 1000ms




                                                       11
Closure memoization
  def plus = { a, b -> sleep 1000; a + b }.memoize()

  assert   plus(1,   2)   ==   3   //   after 1000ms
  assert   plus(1,   2)   ==   3   //   return immediately
  assert   plus(2,   2)   ==   4   //   after 1000ms
  assert   plus(2,   2)   ==   4   //   return immediately  




                                                               11
Closure memoization
  def plus = { a, b -> sleep 1000; a + b }.memoize()

  assert   plus(1,   2)   ==   3   //   after 1000ms
  assert   plus(1,   2)   ==   3   //   return immediately
  assert   plus(2,   2)   ==   4   //   after 1000ms
  assert   plus(2,   2)   ==   4   //   return immediately  
   




                                                               11
Closure memoization
  def plus = { a, b -> sleep 1000; a + b }.memoize()

  assert plus(1, 2) == 3 //    after 1000ms
  assert plus(1, 2) == 3 //    return immediately
  assert plus(2, 2) == 4 //    after 1000ms
  assert plus(2, 2) == 4 //    return immediately  
   
  // at least 10 invocations   cached




                                                       11
Closure memoization
  def plus = { a, b -> sleep 1000; a + b }.memoize()

  assert plus(1, 2) == 3 // after 1000ms
  assert plus(1, 2) == 3 // return immediately
  assert plus(2, 2) == 4 // after 1000ms
  assert plus(2, 2) == 4 // return immediately  
   
  // at least 10 invocations cached
  def plusAtLeast = { ... }.memoizeAtLeast(10)




                                                       11
Closure memoization
  def plus = { a, b -> sleep 1000; a + b }.memoize()

  assert plus(1, 2) == 3 // after 1000ms
  assert plus(1, 2) == 3 // return immediately
  assert plus(2, 2) == 4 // after 1000ms
  assert plus(2, 2) == 4 // return immediately  
   
  // at least 10 invocations cached
  def plusAtLeast = { ... }.memoizeAtLeast(10)
   




                                                       11
Closure memoization
  def plus = { a, b -> sleep 1000; a + b }.memoize()

  assert plus(1, 2) == 3 // after 1000ms
  assert plus(1, 2) == 3 // return immediately
  assert plus(2, 2) == 4 // after 1000ms
  assert plus(2, 2) == 4 // return immediately  
   
  // at least 10 invocations cached
  def plusAtLeast = { ... }.memoizeAtLeast(10)
   
  // at most 10 invocations cached




                                                       11
Closure memoization
  def plus = { a, b -> sleep 1000; a + b }.memoize()

  assert plus(1, 2) == 3 // after 1000ms
  assert plus(1, 2) == 3 // return immediately
  assert plus(2, 2) == 4 // after 1000ms
  assert plus(2, 2) == 4 // return immediately  
   
  // at least 10 invocations cached
  def plusAtLeast = { ... }.memoizeAtLeast(10)
   
  // at most 10 invocations cached
  def plusAtMost = { ... }.memoizeAtMost(10) 




                                                       11
Closure memoization
  def plus = { a, b -> sleep 1000; a + b }.memoize()

  assert plus(1, 2) == 3 // after 1000ms
  assert plus(1, 2) == 3 // return immediately
  assert plus(2, 2) == 4 // after 1000ms
  assert plus(2, 2) == 4 // return immediately  
   
  // at least 10 invocations cached
  def plusAtLeast = { ... }.memoizeAtLeast(10)
   
  // at most 10 invocations cached
  def plusAtMost = { ... }.memoizeAtMost(10) 

  // between 10 and 20 invocations cached




                                                       11
Closure memoization
  def plus = { a, b -> sleep 1000; a + b }.memoize()

  assert plus(1, 2) == 3 // after 1000ms
  assert plus(1, 2) == 3 // return immediately
  assert plus(2, 2) == 4 // after 1000ms
  assert plus(2, 2) == 4 // return immediately  
   
  // at least 10 invocations cached
  def plusAtLeast = { ... }.memoizeAtLeast(10)
   
  // at most 10 invocations cached
  def plusAtMost = { ... }.memoizeAtMost(10) 

  // between 10 and 20 invocations cached
  def plusAtLeast = { ... }.memoizeBetween(10, 20)


                                                       11
Builtin JSON support

 •   Consuming


 •   Producing


 •   Pretty-printing




                       12
Builtin JSON support

  import groovy.json.* 

  def payload = new URL(
    "http://github.../json/commits/...").text 

  def slurper = new JsonSlurper()
  def doc = slurper.parseText(payload) 

  doc.commits.message.each { println it }




                                                 13
Builtin JSON support
import groovy.json.* 
 
def json = new JsonBuilder() 
 
json.person {    
   name "Guillaume"
   age 35    
   pets "Hector", "Felix"
} 
println json.toString()




                                14
Builtin JSON support
import groovy.json.* 
 
def json = new JsonBuilder() 
 
json.person {                 {    
   name "Guillaume"               "person": {        
                                    "name": "Guillaume",        
   age 35                           "age": 35,        
   pets "Hector", "Felix"           "pets": [            
}                                      "Hector",            
println json.toString()                "Felix"        
                                           ]    
                                       }
                                   }


                                                                   14
Builtin JSON support
  import groovy.json.* 
   
  println JsonOutput.prettyPrint(
     '{"person":{"name":"Guillaume","age":35,' +
     '"pets":["Hector","Felix"]}}')

                 {    
                     "person": {        
                       "name": "Guillaume",        
                       "age": 35,        
                       "pets": [            
                           "Hector",            
                           "Felix"        
                       ]    
                     }
                 }
                                                      15
New AST transformations
•       @Log                  •       Controlling execution
                                  •    @ThreadInterrupt

•       @Field                    •    @TimedInterrupt
                                  •    @ConditionalInterrupt


•       @AutoClone
                              •       @InheritConstructor
•       @AutoExternalizable

                              •       @WithReadLock
•       @Canonical
                              •       @WithWriteLock
    •    @ToString
    •    @EqualsAndHashCode
    •    @TupleConstructor    •       @ListenerList

                                                               16
@Log
•   Four different loggers can be injected
    •@Log
    •@Commons                   import groovy.util.logging.* 
    •@Log4j                      
                                @Log
    •@Slf4j                     class Car {    
                                    Car() {        
                                      log.info 'Car constructed'    
•   Possible to implement
                                 } 
                                    }
    your own strategy             
                                 def c = new Car()




                                                                       17
@Log
•   Four different loggers can be injected
    •@Log
    •@Commons                   import groovy.util.logging.* 
    •@Log4j                      
                                @Log
    •@Slf4j
                   Guarded
                    w/ an if
                                class Car {    
                                    Car() {        
                                      log.info 'Car constructed'    
•   Possible to implement
                                 } 
                                    }
    your own strategy             
                                 def c = new Car()




                                                                       17
Controlling code execution
 •   Your application may run user’s code
     •what if the code runs in infinite loops or for too long?
     •what if the code consumes too many resources?


 •   3 new transforms at your rescue
     •@ThreadInterrupt: adds Thread#isInterrupted checks
      so your executing thread stops when interrupted
     •@TimedInterrupt: adds checks in method and
      closure bodies to verify it’s run longer than expected
     •@ConditionalInterrupt: adds checks with your own
      conditional logic to break out from the user code
                                                                18
@ThreadInterrupt

   @ThreadInterrupt
   import groovy.transform.ThreadInterrupt 
    
   while (true) {


       // eat lots of CPU
   }




                                              19
@ThreadInterrupt

      @ThreadInterrupt
      import groovy.transform.ThreadInterrupt 
       
      while (true) {

  {     if (Thread.currentThread().isInterrupted())
            throw new InterruptedException()
        // eat lots of CPU
      }




                                                      19
@ToString
•       Provides a default toString() method to your types
•       Available annotation options
    •    includeNames, includeFields, includeSuper, excludes

                  import groovy.transform.ToString 
                   
                  @ToString
                  class Person {    
                     String name    
                     int age
                  } 
                   
                  println new Person(name: 'Pete', age: 15)
                  // => Person(Pete, 15)

                                                               20
@EqualsAndHashCode
•   Provides default implementations for equals() and
    hashCode() methods
            import groovy.transform.EqualsAndHashCode 
             
            @EqualsAndHashCode
            class Coord {    
               int x, y
            } 
             
            def c1 = new Coord(x: 20, y: 5)
            def c2 = new Coord(x: 20, y: 5) 
             
            assert c1 == c2
            assert c1.hashCode() == c2.hashCode()

                                                         21
@TupleConstructor
•   Provides a « classical » constructor with all properties
•   Several annotation parameter options available

              import groovy.transform.TupleConstructor 
               
              @TupleConstructor
              class Person {    
                 String name    
                 int age
              } 
               
              def m = new Person('Marion', 4)      
               
              assert m.name == 'Marion'
              assert m.age == 4

                                                               22
@InheritConstructors
•   Classes like Exception are painful when extended,
    as all the base constructors should be replicated




    class CustomException extends Exception {
       CustomException()               { super()     }
       CustomException(String msg)         { super(msg) }
       CustomException(String msg, Throwable t) { super(msg, t) }
       CustomException(Throwable t)         { super(t)   }
    }




                                                                    23
@InheritConstructors
•   Classes like Exception are painful when extended,
    as all the base constructors should be replicated

    import groovy.transform.*

    @InheritConstructors
    class CustomException extends Exception {
       CustomException()               { super()     }
       CustomException(String msg)         { super(msg) }
       CustomException(String msg, Throwable t) { super(msg, t) }
       CustomException(Throwable t)         { super(t)   }
    }




                                                                    23
Miscellaneous
 •   Compilation customizers
 •   Java 7 diamond operator
 •   Slashy and dollar slashy strings
 •   New GDK methods
 •   (G)String to Enum coercion
 •   Customizing the Groovysh prompt
 •   Executing remote scripts




                                        24
What’s
in store
for 2.0?
Groovy 2.0
 •   A more modular Groovy
 •   Java 7 alignements: Project Coin
     • binary literals
     • underscore in literals
     • multicatch
 •   JDK 7: InvokeDynamic
 •   Static type checking
 •   Static compilation




                                        26
Groovy Modularity
 •   Groovy’s « all » JAR weighs in at 6 MB


 • Nobody needs everything
  • Template engine, Ant scripting, Swing UI building...
 •   Provide a smaller core
     •and several smaller JARs per feature


 •   Provide hooks for setting up DGM methods, etc.


                                                           27
The new JARs
 •   A smaller groovy.jar: 3MB


 •   Modules
     •console                    •   sql
     •docgenerator               •   swing
     •groovydoc                  •   servlet
     •groovysh                   •   templates
     •ant                        •   test
     •bsf                        •   testng
     •jsr-223                    •   json
     •jmx                        •   xml
                                                 28
Extension modules
 •   Create your own module
     •contribute instance extension methods

 package foo

 class StringExtension {
    static introduces(String self, String name) {
       "Hi ${name), I’m ${self}"
    }
 }

 // usage: "Guillaume".introduces("Cédric")


                                                    29
Extension modules
 •   Create your own module
     •contribute instance extension methods    Same structure
                                                as Categories

 package foo

 class StringExtension {
    static introduces(String self, String name) {
       "Hi ${name), I’m ${self}"
    }
 }

 // usage: "Guillaume".introduces("Cédric")


                                                            29
Extension modules
 •   Create your own module
     •contribute class extension methods

              package foo

              class StaticStringExtension {
                 static hi(String self) {
                    "Hi!"
                 }
              }

              // usage: String.hi()

                                              30
Extension module descriptor
 •   Descriptor in: META-INF/services/
     org.codehaus.groovy.runtime.ExtensionModule


 moduleName = stringExtensions
 moduleVersion = 1.0
 // comma-separated list of classes
 extensionClasses = foo.StringExtension
 // comma-separated list of classes
 staticExtensionClasses = foo.StaticStringExtension




                                                      31
Java 7 / JDK 7

 •   Project Coin and InvokeDynamic




                                      32
Binary literals
•   We had decimal, octal and hexadecimal notations for
    number literals
•   We can now use binary representations too

                 int x = 0b10101111
                 assert x == 175
                  
                 byte aByte = 0b00100001
                 assert aByte == 33
                  
                 int anInt = 0b1010000101000101
                 assert anInt == 41285


                                                          33
Underscore in literals
•   Now we can also add underscores
    in number literals for more readability

    long creditCardNumber = 1234_5678_9012_3456L
    long socialSecurityNumbers = 999_99_9999L
    float monetaryAmount = 12_345_132.12
    long hexBytes = 0xFF_EC_DE_5E
    long hexWords = 0xFFEC_DE5E
    long maxLong = 0x7fff_ffff_ffff_ffffL
    long alsoMaxLong = 9_223_372_036_854_775_807L
    long bytes =
    0b11010010_01101001_10010100_10010010



                                                    34
Multicatch
•   One block for multiple exception caught
    •rather than duplicating the block


        try {
           /* ... */
        } catch(IOException | NullPointerException e) {
           /* one block to treat 2 exceptions */
        }




                                                          35
InvokeDynamic
 • Groovy 2.0 supports JDK 7’s invokeDynamic
  • compiler has a flag for compiling against JDK 7
  • might use the invokeDynamic backport for < JDK 7
 •   Benefits
     • more runtime performance!
         •
        at least as fast as current « dynamic » Groovy
     •in the long run, will allow us to get rid of code!
         •
        call site caching, thanks to MethodHandles
         •
        metaclass registry, thanks to ClassValues
         •
        will let the JIT inline calls more easily
                                                           36
Static Type Checking
 •   Goal: make the Groovy compiler «grumpy»!
     •   and throw compilation errors (not at runtime)
 • Not everybody needs dynamic features all the
     time
     •   think Java libraries scripting
 •   Grumpy should...
     •   tell you about your method or variable typos
     •   complain if you call methods that don’t exist
     •   shout on assignments of wrong types
     •   infer the types of your variables
     •   figure out GDK methods
     •   etc...
                                                         37
Typos in a variable or

 import groovy.transform.TypeChecked
  
 void method() {}
  
 @TypeChecked test() {
   // Cannot find matching method metthhoood()
   metthhoood()
  
   def name = "Guillaume"
   // variable naamme is undeclared
   println naamme
 }



                                                38
Typos in a variable or

 import groovy.transform.TypeChecked
  
 void method() {}
  
 @TypeChecked test() {
   // Cannot find matching method metthhoood()
   metthhoood()
  
   def name = "Guillaume"                  Compilation
   // variable naamme is undeclared           errors!
   println naamme
 }



                                                         38
Typos in a variable or
                                        Annotation can be at
                                        class or method level
 import groovy.transform.TypeChecked
  
 void method() {}
  
 @TypeChecked test() {
   // Cannot find matching method metthhoood()
   metthhoood()
  
   def name = "Guillaume"                  Compilation
   // variable naamme is undeclared           errors!
   println naamme
 }



                                                            38
Wrong assignments

    // cannot assign value of type... to variable...
    int x = new Object()
    Set set = new Object()
     
    def o = new Object()
    int x = o
     
    String[] strings = ['a','b','c']
    int str = strings[0]
     
    // cannot find matching method plus()
    int i = 0
    i += '1'




                                                       39
Wrong assignments

    // cannot assign value of type... to variable...
    int x = new Object()
    Set set = new Object()                             Compilation
                                                       errors!
    def o = new Object()
    int x = o
     
    String[] strings = ['a','b','c']
    int str = strings[0]
     
    // cannot find matching method plus()
    int i = 0
    i += '1'




                                                                     39
Wrong return types
    // checks if/else branch return values
    @TypeChecked
    int method() {
       if (true) { 'String' }
       else { 42 }
    }
    // works for switch/case & try/catch/finally
     
    // transparent toString() implied
    @TypeChecked
    String greeting(String name) {
       def sb = new StringBuilder()
       sb << "Hi " << name
    }



                                                  40
Wrong return types
    // checks if/else branch return values
    @TypeChecked
    int method() {                      Compilation
       if (true) { 'String' }              error!
       else { 42 }
    }
    // works for switch/case & try/catch/finally
     
    // transparent toString() implied
    @TypeChecked
    String greeting(String name) {
       def sb = new StringBuilder()
       sb << "Hi " << name
    }



                                                      40
Type inference
    @TypeChecked test() {
      def name = "  Guillaume  "
     
      // String type infered (even inside GString)
      println "NAME = ${name.toUpperCase()}"
     
      // Groovy GDK method support
      // (GDK operator overloading too)
      println name.trim()
     
      int[] numbers = [1, 2, 3]
      // Element n is an int
      for (int n in numbers) {
         println n
      }
    }



                                                     41
Statically checked & dyn.
     @TypeChecked
     String greeting(String name) {
        // call method with dynamic behavior
        // but with proper signature
        generateMarkup(name.toUpperCase())
     }
      
     // usual dynamic behavior
     String generateMarkup(String name) {
        def sw = new StringWriter()
        new MarkupBuilder(sw).html {
           body {
             div name
           }
        }
        sw.toString()
     }


                                               42
Instanceof checks
   @TypeChecked
   void test(Object val) {

       if (val instanceof String) {
           println val.toUpperCase()
       } else if (val instanceof Number) {
           println "X" * val.intValue()
       }

   }




                                             43
Instanceof checks
                                             No need
   @TypeChecked                              for casts
   void test(Object val) {

       if (val instanceof String) {
           println val.toUpperCase()
       } else if (val instanceof Number) {
           println "X" * val.intValue()
       }

   }




                                                    43
Instanceof checks
                                             No need
   @TypeChecked                              for casts
   void test(Object val) {

       if (val instanceof String) {
           println val.toUpperCase()
       } else if (val instanceof Number) {
           println "X" * val.intValue()
       }

   }


   Can call String#multiply(int)
  from the Groovy Development Kit


                                                    43
Lowest Upper Bound
 •   Represents the lowest « super » type classes
     have in common
     •may be virtual (aka « non-denotable »)


           @TypeChecked test() {
             // an integer and a BigDecimal
             return [1234, 3.14]
           }




                                                    44
Lowest Upper Bound
 •   Represents the lowest « super » type classes
     have in common
     •may be virtual (aka « non-denotable »)


           @TypeChecked test() {
             // an integer and a BigDecimal
             return [1234, 3.14]
           }


                         Inferred return type:
                     List<Number & Comparable>
                                                    44
Lowest Upper Bound
 •   Represents the lowest « super » type classes
     have in common
     •may be virtual (aka « non-denotable »)


           @TypeChecked test() {
             // an integer and a BigDecimal
             return [1234, 3.14]
           }


                         Inferred return type:
                     List<Number & Comparable>
                                                    44
Flow typing
 •       Static type checking shouldn’t complain even for bad coding
         practicies which work without type checks

     @TypeChecked test() {
       def var = 123       // inferred type is int
       int x = var      // var is an int
       var = "123"       // assign var with a String

          x = var.toInteger() // no problem, no need to cast

          var = 123
          x = var.toUpperCase() // error, var is int!
     }




                                                                  45
Gotcha: static checking vs
 •   Type checking works at compile-time
     •adding @TypeChecked doesn’t change behavior
         •
        do not confuse with static compilation


 •   Most dynamic features cannot be type checked
     •metaclass changes, categories
     •dynamically bound variables (ex: script’s binding)


 •   However, compile-time metaprogramming works
     •as long as proper type information is defined

                                                           46
Gotcha: runtime

     @TypeChecked
     void test() {
       Integer.metaClass.foo = {}
       123.foo()
     }




                                    47
Gotcha: runtime

     @TypeChecked
     void test() {
       Integer.metaClass.foo = {}
       123.foo()
     }


                       Not allowed:
                    metaClass property
                       is dynamic



                                         47
Gotcha: runtime

     @TypeChecked
     void test() {
       Integer.metaClass.foo = {}
       123.foo()
     }


       Method not      Not allowed:
       recognized   metaClass property
                       is dynamic



                                         47
Gotcha: explicit type for
 @TypeChecked test() {
   ["a", "b", "c"].collect {
      it.toUpperCase() // Not OK
   }
 }



 •   A « Groovy Enhancement Proposal » to address the issue




                                                              48
Gotcha: explicit type for
 @TypeChecked test() {
   ["a", "b", "c"].collect { String it ->
      it.toUpperCase() // OK, it’s a String
   }
 }



 •   A « Groovy Enhancement Proposal » to address the issue




                                                              48
Closure shared variables

      @TypeChecked test() {
        def var = "abc"
        def cl = { var = new Date() }
        cl()
        var.toUpperCase() // Not OK!
      }




                                        49
Closure shared variables
                          var assigned in the closure:
                           «shared closure variable»

      @TypeChecked test() {
        def var = "abc"
        def cl = { var = new Date() }
        cl()
        var.toUpperCase() // Not OK!
      }




                                                         49
Closure shared variables
                                     var assigned in the closure:
                                      «shared closure variable»

                 @TypeChecked test() {
 Impossible to
  ensure the
                   def var = "abc"
 assignment        def cl = { var = new Date() }
really happens     cl()
                   var.toUpperCase() // Not OK!
                 }




                                                                    49
Closure shared variables
                                          var assigned in the closure:
                                           «shared closure variable»

                 @TypeChecked test() {
 Impossible to
  ensure the
                   def var = "abc"
 assignment        def cl = { var = new Date() }
really happens     cl()
                   var.toUpperCase() // Not OK!
                 }



                  Only methods of the most specific
                     compatible type (LUB) are
                    allowed by the type checker

                                                                         49
Closure shared variables
     class A       { void foo() {} }
     class B extends A { void bar() {} }

     @TypeChecked test() {
       def var = new A()
       def cl = { var = new B() }
       cl()
       var.foo() // OK!
     }




                                           50
Closure shared variables
     class A       { void foo() {} }
     class B extends A { void bar() {} }

     @TypeChecked test() {
       def var = new A()
       def cl = { var = new B() }
       cl()
       var.foo() // OK!
     }


         var is at least
        an instance of A


                                           50
Static Compilation

 •   Given your Groovy code can be type checked...
     we can as well compile it « statically »


     •   ie. generate the same byte code as javac


 •   Also interesting for those stuck in JDK < 7
     to benefit from performance improvements




                                                     51
Static Compilation:
 •   You gain:
     •Type safety
      • thanks to static type checking
          •
          static compilation builds upon static type checking
     •Faster code
      • as close as possible to Java’s performance
     •Code immune to « monkey patching »
      • metaprogramming badly used can interfere with
        framework code
     •Smaller bytecode size

                                                                52
Static Compilation:
 •   But you loose:


     •   Dynamic features
         •metaclass changes, categories, etc.


     •   Dynamic method dispatch
         •although as close as possible to « dynamic » Groovy




                                                                53
Statically compiled & dyn.
     @CompileStatic
     String greeting(String name) {
        // call method with dynamic behavior
        // but with proper signature
        generateMarkup(name.toUpperCase())
     }
      
     // usual dynamic behavior
     String generateMarkup(String name) {
        def sw = new StringWriter()
        new MarkupBuilder(sw).html {
           body {
             div name
           }
        }
        sw.toString()
     }

                                               54
What about performance?
 •   Comparisons between:


     •   Java


     •   Groovy static compilation (Groovy 2.0)
     •   Groovy with primitive optimizations (Groovy 1.8+)
     •   Groovy without optimizations (Groovy 1.7)




                                                        55
What about performance?
                                            Pi (π)     Binary
                              Fibonacci
                                          quadrature   trees

                  Java        191 ms        97 ms      3.6 s

                Static
1.7 1.8 2.0




              compilation
                              197 ms      101 ms       4.3 s

                Primitive
              optimizations
                              360 ms       111 ms      23.7 s

                No prim.
              optimizations
                              2590 ms     3220 ms      50.0 s


                                                                56
Summary
 •   Main themes of the Groovy 2.0 release
     •Modularity


     •   Embark the JDK 7 enhancements
         •Project Coin
         •Invoke Dynamic


     •   Static aspects
         • Static type checking
         • Static compilation

                                             57
Thank you!



                           ge
                    e Lafor lopment
       Gu illaum ovy Deve
                 Gro
       H ead of
                                  om
                      ge@ gmail.c
        Emai l: glafor forge               e
                  :@  gla       .to/glaforg
        Twitter : http://gplus spot.com
                   +             pp
         Google p://glaforge.a
                  tt
          Blog: h




                                               58
Questions & Answers
 •   Got questions, really?


                              Q&A




                                    59
Image credits
 •   Bugs bunny: http://storage.canalblog.com/63/56/517188/47634843.jpeg

 •   Pills: http://www.we-ew.com/wp-content/uploads/2011/01/plan-b-pills.jpg

 •   Chains: http://2.bp.blogspot.com/-GXDVqUYSCa0/TVdBsON4tdI/AAAAAAAAAW4/EgJOUmAxB28/s1600/breaking-chains5_copy9611.jpg

 •   Slurp: http://www.ohpacha.com/218-532-thickbox/gamelle-slurp.jpg

 •   Grumpy: http://mafeuilledechou.fr/__oneclick_uploads/2010/05/grumpy.jpg

 •   Modularity: http://php.jglobal.com/blog/wp-content/uploads/2009/11/modularity.jpg

 •   Agenda: http://www.plombiereslesbains.fr/images/stories/agenda.jpg

 •   Java 7: http://geeknizer.com/wp-content/uploads/java7.jpg

 •   Road Runner: http://newspaper.li/static/4ada046b7772f0612fec4e3840142308.jpg

 •   Porky: http://joshuadsandy.files.wordpress.com/2011/05/porky-pig-5.jpg

 •   Will E help: http://www.clipart-fr.com/data/clipart/looney/looney_004.jpg

 •   Coyote road runner: http://www.jenkle.com/wp-content/uploads/2010/12/coyote-wallpaper1.jpg

 •   Lube: http://images.motorcycle-superstore.com/ProductImages/OG/0000_Motul_Chain_Lube_Road_--.jpg




                                                                                                                             60

Contenu connexe

Tendances

Groovy 2.0 - Devoxx France 2012
Groovy 2.0 - Devoxx France 2012Groovy 2.0 - Devoxx France 2012
Groovy 2.0 - Devoxx France 2012Guillaume Laforge
 
Groovy update - S2GForum London 2011 - Guillaume Laforge
Groovy update - S2GForum London 2011 - Guillaume LaforgeGroovy update - S2GForum London 2011 - Guillaume Laforge
Groovy update - S2GForum London 2011 - Guillaume LaforgeGuillaume Laforge
 
Intro to pl/PHP Oscon2007
Intro to pl/PHP Oscon2007Intro to pl/PHP Oscon2007
Intro to pl/PHP Oscon2007Robert Treat
 
What you need to remember when you upload to CPAN
What you need to remember when you upload to CPANWhat you need to remember when you upload to CPAN
What you need to remember when you upload to CPANcharsbar
 
Ten common mistakes made in Function Java - iSense Java Summit
Ten common mistakes made in Function Java - iSense Java SummitTen common mistakes made in Function Java - iSense Java Summit
Ten common mistakes made in Function Java - iSense Java SummitBrian Vermeer
 
Ten common mistakes made in Function Java
Ten common mistakes made in Function JavaTen common mistakes made in Function Java
Ten common mistakes made in Function JavaBrian Vermeer
 
Intro to Testing in Zope, Plone
Intro to Testing in Zope, PloneIntro to Testing in Zope, Plone
Intro to Testing in Zope, PloneQuintagroup
 
Can you upgrade to Puppet 4.x?
Can you upgrade to Puppet 4.x?Can you upgrade to Puppet 4.x?
Can you upgrade to Puppet 4.x?Martin Alfke
 
Athenticated smaba server config with open vpn
Athenticated smaba server  config with open vpnAthenticated smaba server  config with open vpn
Athenticated smaba server config with open vpnChanaka Lasantha
 
Common mistakes functional java vjug
Common mistakes functional java vjugCommon mistakes functional java vjug
Common mistakes functional java vjugBrian Vermeer
 
Common mistakes functional java | Oracle Code One 2018
Common mistakes functional java | Oracle Code One 2018Common mistakes functional java | Oracle Code One 2018
Common mistakes functional java | Oracle Code One 2018Brian Vermeer
 
Ten common mistakes made with Functional Java JBCNConf18
Ten common mistakes made with Functional Java JBCNConf18Ten common mistakes made with Functional Java JBCNConf18
Ten common mistakes made with Functional Java JBCNConf18Brian Vermeer
 
Postgres-BDR with Google Cloud Platform
Postgres-BDR with Google Cloud PlatformPostgres-BDR with Google Cloud Platform
Postgres-BDR with Google Cloud PlatformSungJae Yun
 
Xen server 6.0 xe command reference (1.1)
Xen server 6.0 xe command reference (1.1)Xen server 6.0 xe command reference (1.1)
Xen server 6.0 xe command reference (1.1)Timote Lima
 

Tendances (20)

Whats new in Groovy 2.0?
Whats new in Groovy 2.0?Whats new in Groovy 2.0?
Whats new in Groovy 2.0?
 
Groovy 2.0 - Devoxx France 2012
Groovy 2.0 - Devoxx France 2012Groovy 2.0 - Devoxx France 2012
Groovy 2.0 - Devoxx France 2012
 
Groovy update - S2GForum London 2011 - Guillaume Laforge
Groovy update - S2GForum London 2011 - Guillaume LaforgeGroovy update - S2GForum London 2011 - Guillaume Laforge
Groovy update - S2GForum London 2011 - Guillaume Laforge
 
Intro to pl/PHP Oscon2007
Intro to pl/PHP Oscon2007Intro to pl/PHP Oscon2007
Intro to pl/PHP Oscon2007
 
What you need to remember when you upload to CPAN
What you need to remember when you upload to CPANWhat you need to remember when you upload to CPAN
What you need to remember when you upload to CPAN
 
Ten common mistakes made in Function Java - iSense Java Summit
Ten common mistakes made in Function Java - iSense Java SummitTen common mistakes made in Function Java - iSense Java Summit
Ten common mistakes made in Function Java - iSense Java Summit
 
Ten common mistakes made in Function Java
Ten common mistakes made in Function JavaTen common mistakes made in Function Java
Ten common mistakes made in Function Java
 
Intro to Testing in Zope, Plone
Intro to Testing in Zope, PloneIntro to Testing in Zope, Plone
Intro to Testing in Zope, Plone
 
Advanced GAR
Advanced GARAdvanced GAR
Advanced GAR
 
Can you upgrade to Puppet 4.x?
Can you upgrade to Puppet 4.x?Can you upgrade to Puppet 4.x?
Can you upgrade to Puppet 4.x?
 
Centos config
Centos configCentos config
Centos config
 
Adb instructions
Adb instructionsAdb instructions
Adb instructions
 
Athenticated smaba server config with open vpn
Athenticated smaba server  config with open vpnAthenticated smaba server  config with open vpn
Athenticated smaba server config with open vpn
 
Common mistakes functional java vjug
Common mistakes functional java vjugCommon mistakes functional java vjug
Common mistakes functional java vjug
 
Common mistakes functional java | Oracle Code One 2018
Common mistakes functional java | Oracle Code One 2018Common mistakes functional java | Oracle Code One 2018
Common mistakes functional java | Oracle Code One 2018
 
Ten common mistakes made with Functional Java JBCNConf18
Ten common mistakes made with Functional Java JBCNConf18Ten common mistakes made with Functional Java JBCNConf18
Ten common mistakes made with Functional Java JBCNConf18
 
Postgres-BDR with Google Cloud Platform
Postgres-BDR with Google Cloud PlatformPostgres-BDR with Google Cloud Platform
Postgres-BDR with Google Cloud Platform
 
Puppet modules for Fun and Profit
Puppet modules for Fun and ProfitPuppet modules for Fun and Profit
Puppet modules for Fun and Profit
 
Hadoop completereference
Hadoop completereferenceHadoop completereference
Hadoop completereference
 
Xen server 6.0 xe command reference (1.1)
Xen server 6.0 xe command reference (1.1)Xen server 6.0 xe command reference (1.1)
Xen server 6.0 xe command reference (1.1)
 

Similaire à JavaOne 2012 Groovy update

How Does Kubernetes Build OpenAPI Specifications?
How Does Kubernetes Build OpenAPI Specifications?How Does Kubernetes Build OpenAPI Specifications?
How Does Kubernetes Build OpenAPI Specifications?reallavalamp
 
Puppet Camp Charlotte 2015: Exporting Resources: There and Back Again
Puppet Camp Charlotte 2015: Exporting Resources: There and Back AgainPuppet Camp Charlotte 2015: Exporting Resources: There and Back Again
Puppet Camp Charlotte 2015: Exporting Resources: There and Back AgainPuppet
 
Groovy Ecosystem - JFokus 2011 - Guillaume Laforge
Groovy Ecosystem - JFokus 2011 - Guillaume LaforgeGroovy Ecosystem - JFokus 2011 - Guillaume Laforge
Groovy Ecosystem - JFokus 2011 - Guillaume LaforgeGuillaume Laforge
 
Java 어플리케이션 성능튜닝 Part1
Java 어플리케이션 성능튜닝 Part1Java 어플리케이션 성능튜닝 Part1
Java 어플리케이션 성능튜닝 Part1상욱 송
 
Tools and Tips for Moodle Developers - #mootus16
 Tools and Tips for Moodle Developers - #mootus16 Tools and Tips for Moodle Developers - #mootus16
Tools and Tips for Moodle Developers - #mootus16Dan Poltawski
 
Morpheus configuration engine (slides from Saint Perl-2 conference)
Morpheus configuration engine (slides from Saint Perl-2 conference)Morpheus configuration engine (slides from Saint Perl-2 conference)
Morpheus configuration engine (slides from Saint Perl-2 conference)Vyacheslav Matyukhin
 
20140406 loa days-tdd-with_puppet_tutorial
20140406 loa days-tdd-with_puppet_tutorial20140406 loa days-tdd-with_puppet_tutorial
20140406 loa days-tdd-with_puppet_tutorialgarrett honeycutt
 
fog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the Cloudfog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the CloudWesley Beary
 
Puppet Modules for Fun and Profit
Puppet Modules for Fun and ProfitPuppet Modules for Fun and Profit
Puppet Modules for Fun and ProfitPuppet
 
Admins: Smoke Test Your Hadoop Cluster!
Admins: Smoke Test Your Hadoop Cluster!Admins: Smoke Test Your Hadoop Cluster!
Admins: Smoke Test Your Hadoop Cluster!Michael Arnold
 
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)Wesley Beary
 
Building apache modules
Building apache modulesBuilding apache modules
Building apache modulesMarian Marinov
 
Inside the JVM - Follow the white rabbit!
Inside the JVM - Follow the white rabbit!Inside the JVM - Follow the white rabbit!
Inside the JVM - Follow the white rabbit!Sylvain Wallez
 
TDD with Puppet Tutorial presented at Cascadia IT Conference 2014-03-07
TDD with Puppet Tutorial presented at Cascadia IT Conference 2014-03-07TDD with Puppet Tutorial presented at Cascadia IT Conference 2014-03-07
TDD with Puppet Tutorial presented at Cascadia IT Conference 2014-03-07garrett honeycutt
 
2016 W3C Conference #4 : ANGULAR + ES6
2016 W3C Conference #4 : ANGULAR + ES62016 W3C Conference #4 : ANGULAR + ES6
2016 W3C Conference #4 : ANGULAR + ES6양재동 코드랩
 
Orchestrated Functional Testing with Puppet-spec and Mspectator
Orchestrated Functional Testing with Puppet-spec and MspectatorOrchestrated Functional Testing with Puppet-spec and Mspectator
Orchestrated Functional Testing with Puppet-spec and MspectatorRaphaël PINSON
 
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...Puppet
 

Similaire à JavaOne 2012 Groovy update (20)

How Does Kubernetes Build OpenAPI Specifications?
How Does Kubernetes Build OpenAPI Specifications?How Does Kubernetes Build OpenAPI Specifications?
How Does Kubernetes Build OpenAPI Specifications?
 
Puppet Camp Charlotte 2015: Exporting Resources: There and Back Again
Puppet Camp Charlotte 2015: Exporting Resources: There and Back AgainPuppet Camp Charlotte 2015: Exporting Resources: There and Back Again
Puppet Camp Charlotte 2015: Exporting Resources: There and Back Again
 
Groovy Ecosystem - JFokus 2011 - Guillaume Laforge
Groovy Ecosystem - JFokus 2011 - Guillaume LaforgeGroovy Ecosystem - JFokus 2011 - Guillaume Laforge
Groovy Ecosystem - JFokus 2011 - Guillaume Laforge
 
Java 어플리케이션 성능튜닝 Part1
Java 어플리케이션 성능튜닝 Part1Java 어플리케이션 성능튜닝 Part1
Java 어플리케이션 성능튜닝 Part1
 
Tools and Tips for Moodle Developers - #mootus16
 Tools and Tips for Moodle Developers - #mootus16 Tools and Tips for Moodle Developers - #mootus16
Tools and Tips for Moodle Developers - #mootus16
 
Cooking with Chef
Cooking with ChefCooking with Chef
Cooking with Chef
 
Morpheus configuration engine (slides from Saint Perl-2 conference)
Morpheus configuration engine (slides from Saint Perl-2 conference)Morpheus configuration engine (slides from Saint Perl-2 conference)
Morpheus configuration engine (slides from Saint Perl-2 conference)
 
20140406 loa days-tdd-with_puppet_tutorial
20140406 loa days-tdd-with_puppet_tutorial20140406 loa days-tdd-with_puppet_tutorial
20140406 loa days-tdd-with_puppet_tutorial
 
fog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the Cloudfog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the Cloud
 
Puppet Modules for Fun and Profit
Puppet Modules for Fun and ProfitPuppet Modules for Fun and Profit
Puppet Modules for Fun and Profit
 
Admins: Smoke Test Your Hadoop Cluster!
Admins: Smoke Test Your Hadoop Cluster!Admins: Smoke Test Your Hadoop Cluster!
Admins: Smoke Test Your Hadoop Cluster!
 
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
 
Building apache modules
Building apache modulesBuilding apache modules
Building apache modules
 
Inside the JVM - Follow the white rabbit!
Inside the JVM - Follow the white rabbit!Inside the JVM - Follow the white rabbit!
Inside the JVM - Follow the white rabbit!
 
TDD with Puppet Tutorial presented at Cascadia IT Conference 2014-03-07
TDD with Puppet Tutorial presented at Cascadia IT Conference 2014-03-07TDD with Puppet Tutorial presented at Cascadia IT Conference 2014-03-07
TDD with Puppet Tutorial presented at Cascadia IT Conference 2014-03-07
 
Testing con spock
Testing con spockTesting con spock
Testing con spock
 
[W3C HTML5 2016] Angular + ES6
[W3C HTML5 2016] Angular + ES6[W3C HTML5 2016] Angular + ES6
[W3C HTML5 2016] Angular + ES6
 
2016 W3C Conference #4 : ANGULAR + ES6
2016 W3C Conference #4 : ANGULAR + ES62016 W3C Conference #4 : ANGULAR + ES6
2016 W3C Conference #4 : ANGULAR + ES6
 
Orchestrated Functional Testing with Puppet-spec and Mspectator
Orchestrated Functional Testing with Puppet-spec and MspectatorOrchestrated Functional Testing with Puppet-spec and Mspectator
Orchestrated Functional Testing with Puppet-spec and Mspectator
 
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
Orchestrated Functional Testing with Puppet-spec and Mspectator - PuppetConf ...
 

Plus de Guillaume Laforge

Lift off with Groovy 2 at JavaOne 2013
Lift off with Groovy 2 at JavaOne 2013Lift off with Groovy 2 at JavaOne 2013
Lift off with Groovy 2 at JavaOne 2013Guillaume Laforge
 
Groovy workshop à Mix-IT 2013
Groovy workshop à Mix-IT 2013Groovy workshop à Mix-IT 2013
Groovy workshop à Mix-IT 2013Guillaume Laforge
 
Les nouveautés de Groovy 2 -- Mix-IT 2013
Les nouveautés de Groovy 2 -- Mix-IT 2013Les nouveautés de Groovy 2 -- Mix-IT 2013
Les nouveautés de Groovy 2 -- Mix-IT 2013Guillaume Laforge
 
Groovy Domain Specific Languages - SpringOne2GX 2012
Groovy Domain Specific Languages - SpringOne2GX 2012Groovy Domain Specific Languages - SpringOne2GX 2012
Groovy Domain Specific Languages - SpringOne2GX 2012Guillaume Laforge
 
Going to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific LanguagesGoing to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific LanguagesGuillaume Laforge
 
GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
GPars et PrettyTime - Paris JUG 2011 - Guillaume LaforgeGPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
GPars et PrettyTime - Paris JUG 2011 - Guillaume LaforgeGuillaume Laforge
 
Gaelyk update - Guillaume Laforge - SpringOne2GX 2011
Gaelyk update - Guillaume Laforge - SpringOne2GX 2011Gaelyk update - Guillaume Laforge - SpringOne2GX 2011
Gaelyk update - Guillaume Laforge - SpringOne2GX 2011Guillaume Laforge
 
Groovy DSLs, from Beginner to Expert - Guillaume Laforge and Paul King - Spri...
Groovy DSLs, from Beginner to Expert - Guillaume Laforge and Paul King - Spri...Groovy DSLs, from Beginner to Expert - Guillaume Laforge and Paul King - Spri...
Groovy DSLs, from Beginner to Expert - Guillaume Laforge and Paul King - Spri...Guillaume Laforge
 
Cloud foundry intro with groovy
Cloud foundry intro with groovyCloud foundry intro with groovy
Cloud foundry intro with groovyGuillaume Laforge
 
Groovy DSLs - S2GForum London 2011 - Guillaume Laforge
Groovy DSLs - S2GForum London 2011 - Guillaume LaforgeGroovy DSLs - S2GForum London 2011 - Guillaume Laforge
Groovy DSLs - S2GForum London 2011 - Guillaume LaforgeGuillaume Laforge
 
Gaelyk - Guillaume Laforge - GR8Conf Europe 2011
Gaelyk - Guillaume Laforge - GR8Conf Europe 2011Gaelyk - Guillaume Laforge - GR8Conf Europe 2011
Gaelyk - Guillaume Laforge - GR8Conf Europe 2011Guillaume Laforge
 
Groovy 1.8 update - Guillaume Laforge - GR8Conf Europe 2011
Groovy 1.8 update - Guillaume Laforge - GR8Conf Europe 2011Groovy 1.8 update - Guillaume Laforge - GR8Conf Europe 2011
Groovy 1.8 update - Guillaume Laforge - GR8Conf Europe 2011Guillaume Laforge
 
Gaelyk - JFokus 2011 - Guillaume Laforge
Gaelyk - JFokus 2011 - Guillaume LaforgeGaelyk - JFokus 2011 - Guillaume Laforge
Gaelyk - JFokus 2011 - Guillaume LaforgeGuillaume Laforge
 
Groovy and Gaelyk - Lausanne JUG 2011 - Guillaume Laforge
Groovy and Gaelyk - Lausanne JUG 2011 - Guillaume LaforgeGroovy and Gaelyk - Lausanne JUG 2011 - Guillaume Laforge
Groovy and Gaelyk - Lausanne JUG 2011 - Guillaume LaforgeGuillaume Laforge
 
Gaelyk - Paris GGUG 2011 - Guillaume Laforge
Gaelyk - Paris GGUG 2011 - Guillaume LaforgeGaelyk - Paris GGUG 2011 - Guillaume Laforge
Gaelyk - Paris GGUG 2011 - Guillaume LaforgeGuillaume Laforge
 
Gaelyk - Groovy Grails eXchange 2010 - Guillaume Laforge
Gaelyk - Groovy Grails eXchange 2010 - Guillaume LaforgeGaelyk - Groovy Grails eXchange 2010 - Guillaume Laforge
Gaelyk - Groovy Grails eXchange 2010 - Guillaume LaforgeGuillaume Laforge
 

Plus de Guillaume Laforge (18)

Lift off with Groovy 2 at JavaOne 2013
Lift off with Groovy 2 at JavaOne 2013Lift off with Groovy 2 at JavaOne 2013
Lift off with Groovy 2 at JavaOne 2013
 
Groovy workshop à Mix-IT 2013
Groovy workshop à Mix-IT 2013Groovy workshop à Mix-IT 2013
Groovy workshop à Mix-IT 2013
 
Les nouveautés de Groovy 2 -- Mix-IT 2013
Les nouveautés de Groovy 2 -- Mix-IT 2013Les nouveautés de Groovy 2 -- Mix-IT 2013
Les nouveautés de Groovy 2 -- Mix-IT 2013
 
Groovy 2 and beyond
Groovy 2 and beyondGroovy 2 and beyond
Groovy 2 and beyond
 
Groovy 2.0 webinar
Groovy 2.0 webinarGroovy 2.0 webinar
Groovy 2.0 webinar
 
Groovy Domain Specific Languages - SpringOne2GX 2012
Groovy Domain Specific Languages - SpringOne2GX 2012Groovy Domain Specific Languages - SpringOne2GX 2012
Groovy Domain Specific Languages - SpringOne2GX 2012
 
Going to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific LanguagesGoing to Mars with Groovy Domain-Specific Languages
Going to Mars with Groovy Domain-Specific Languages
 
GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
GPars et PrettyTime - Paris JUG 2011 - Guillaume LaforgeGPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
GPars et PrettyTime - Paris JUG 2011 - Guillaume Laforge
 
Gaelyk update - Guillaume Laforge - SpringOne2GX 2011
Gaelyk update - Guillaume Laforge - SpringOne2GX 2011Gaelyk update - Guillaume Laforge - SpringOne2GX 2011
Gaelyk update - Guillaume Laforge - SpringOne2GX 2011
 
Groovy DSLs, from Beginner to Expert - Guillaume Laforge and Paul King - Spri...
Groovy DSLs, from Beginner to Expert - Guillaume Laforge and Paul King - Spri...Groovy DSLs, from Beginner to Expert - Guillaume Laforge and Paul King - Spri...
Groovy DSLs, from Beginner to Expert - Guillaume Laforge and Paul King - Spri...
 
Cloud foundry intro with groovy
Cloud foundry intro with groovyCloud foundry intro with groovy
Cloud foundry intro with groovy
 
Groovy DSLs - S2GForum London 2011 - Guillaume Laforge
Groovy DSLs - S2GForum London 2011 - Guillaume LaforgeGroovy DSLs - S2GForum London 2011 - Guillaume Laforge
Groovy DSLs - S2GForum London 2011 - Guillaume Laforge
 
Gaelyk - Guillaume Laforge - GR8Conf Europe 2011
Gaelyk - Guillaume Laforge - GR8Conf Europe 2011Gaelyk - Guillaume Laforge - GR8Conf Europe 2011
Gaelyk - Guillaume Laforge - GR8Conf Europe 2011
 
Groovy 1.8 update - Guillaume Laforge - GR8Conf Europe 2011
Groovy 1.8 update - Guillaume Laforge - GR8Conf Europe 2011Groovy 1.8 update - Guillaume Laforge - GR8Conf Europe 2011
Groovy 1.8 update - Guillaume Laforge - GR8Conf Europe 2011
 
Gaelyk - JFokus 2011 - Guillaume Laforge
Gaelyk - JFokus 2011 - Guillaume LaforgeGaelyk - JFokus 2011 - Guillaume Laforge
Gaelyk - JFokus 2011 - Guillaume Laforge
 
Groovy and Gaelyk - Lausanne JUG 2011 - Guillaume Laforge
Groovy and Gaelyk - Lausanne JUG 2011 - Guillaume LaforgeGroovy and Gaelyk - Lausanne JUG 2011 - Guillaume Laforge
Groovy and Gaelyk - Lausanne JUG 2011 - Guillaume Laforge
 
Gaelyk - Paris GGUG 2011 - Guillaume Laforge
Gaelyk - Paris GGUG 2011 - Guillaume LaforgeGaelyk - Paris GGUG 2011 - Guillaume Laforge
Gaelyk - Paris GGUG 2011 - Guillaume Laforge
 
Gaelyk - Groovy Grails eXchange 2010 - Guillaume Laforge
Gaelyk - Groovy Grails eXchange 2010 - Guillaume LaforgeGaelyk - Groovy Grails eXchange 2010 - Guillaume Laforge
Gaelyk - Groovy Grails eXchange 2010 - Guillaume Laforge
 

Dernier

Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsAndrey Dotsenko
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDGMarianaLemus7
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024BookNet Canada
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Scott Keck-Warren
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsPrecisely
 

Dernier (20)

Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
The transition to renewables in India.pdf
The transition to renewables in India.pdfThe transition to renewables in India.pdf
The transition to renewables in India.pdf
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
APIForce Zurich 5 April Automation LPDG
APIForce Zurich 5 April  Automation LPDGAPIForce Zurich 5 April  Automation LPDG
APIForce Zurich 5 April Automation LPDG
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC BiblioShare - Tech Forum 2024
 
Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024Advanced Test Driven-Development @ php[tek] 2024
Advanced Test Driven-Development @ php[tek] 2024
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Unlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power SystemsUnlocking the Potential of the Cloud for IBM Power Systems
Unlocking the Potential of the Cloud for IBM Power Systems
 

JavaOne 2012 Groovy update

  • 1. What’s new in Groovy 2.0 Guillaume Laforge Groovy Project Manager SpringSource / VMware @glaforge 1
  • 2. Guillaume Laforge • Groovy Project Manager at VMware •Initiator of the Grails framework •Creator of the Gaelyk • Co-author of Groovy in Action • Follow me on... •My blog: http://glaforge.appspot.com •Twitter: @glaforge •Google+: http://gplus.to/glaforge 2
  • 3. Agenda (1/2) • What’s in Groovy 1.8? • Nicer DSLs with command chains • Runtime performance improvements • GPars bundled for taming your multicores • Closure enhancements • Builtin JSON support • New AST transformations 3
  • 4. Agenda (2/2) • What’s new in Groovy 2.0? • Alignments with JDK 7 • Project Coin (small language changes) • Invoke Dynamic support • Continued runtime performance improvements • Static type checking • Static compilation • Modularity 4
  • 5. Command chains • A grammar improvement allowing you to drop dots & parens when chaining method calls • an extended version of top-level statements like println • Less dots, less parens allow you to •write more readable business rules •in almost plain English sentences • (or any language, of course) 5
  • 6. Command chains pull request on github 6
  • 7. Command chains Alternation of method names pull request on github 6
  • 8. Command chains Alternation of method names pull request on github and parameters (even named ones) 6
  • 9. Command chains pull request on github 6
  • 10. Command chains Equivalent to: pull request on github ( ). ( ) 6
  • 12. Command chains // methods with multiple arguments (commas) 7
  • 13. Command chains // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor 7
  • 14. Command chains // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // leverage named-args as punctuation 7
  • 15. Command chains // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // leverage named-args as punctuation check that: margarita  tastes good 7
  • 16. Command chains // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // leverage named-args as punctuation check that: margarita  tastes good // closure parameters for new control structures 7
  • 17. Command chains // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // leverage named-args as punctuation check that: margarita  tastes good // closure parameters for new control structures given {}  when {}  then {} 7
  • 18. Command chains // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // leverage named-args as punctuation check that: margarita  tastes good // closure parameters for new control structures given {}  when {}  then {} // zero-arg methods require parens 7
  • 19. Command chains // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // leverage named-args as punctuation check that: margarita  tastes good // closure parameters for new control structures given {}  when {}  then {} // zero-arg methods require parens select all  unique() from names 7
  • 20. Command chains // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // leverage named-args as punctuation check that: margarita  tastes good // closure parameters for new control structures given {}  when {}  then {} // zero-arg methods require parens select all  unique() from names // possible with an odd number of terms 7
  • 21. Command chains // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // leverage named-args as punctuation check that: margarita  tastes good // closure parameters for new control structures given {}  when {}  then {} // zero-arg methods require parens select all  unique() from names // possible with an odd number of terms take 3  cookies 7
  • 22. Command chains // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor ( ). ( ). ( ) // leverage named-args as punctuation check that: margarita  tastes good // closure parameters for new control structures given {}  when {}  then {} // zero-arg methods require parens select all  unique() from names // possible with an odd number of terms take 3  cookies 7
  • 23. Command chains // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor ( ). ( ). ( ) // leverage named-args as punctuation check that: margarita  )tastes good ( ). ( // closure parameters for new control structures given {}  when {}  then {} // zero-arg methods require parens select all  unique() from names // possible with an odd number of terms take 3  cookies 7
  • 24. Command chains // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor ( ). ( ). ( ) // leverage named-args as punctuation check that: margarita  )tastes good ( ). ( // closure parameters for new control structures given). when {}  ) ( {}  ( ). ( then {} // zero-arg methods require parens select all  unique() from names // possible with an odd number of terms take 3  cookies 7
  • 25. Command chains // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor ( ). ( ). ( ) // leverage named-args as punctuation check that: margarita  )tastes good ( ). ( // closure parameters for new control structures given). when {}  ) ( {}  ( ). ( then {} // zero-arg methods require parens select all  unique() from names ( ). . ( ) // possible with an odd number of terms take 3  cookies 7
  • 26. Command chains // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor ( ). ( ). ( ) // leverage named-args as punctuation check that: margarita  )tastes good ( ). ( // closure parameters for new control structures given). when {}  ) ( {}  ( ). ( then {} // zero-arg methods require parens select all  unique() from names ( ). . ( ) // possible with an odd number of terms take). cookies ( 3  7
  • 27. GPars bundled • GPars is bundled in the Groovy distribution • GPars covers a wide range of parallel and concurrent paradigms •actors, fork/join, map/filter/reduce, dataflow, agents •parallel arrays, executors, STM, and more... • And you can use it from plain Java as well! • http://gpars.codehaus.org/ 8
  • 28. Closure enhancements • Closure annotation parameters • Some more functional flavor • composition • compose several closures into one single closure • trampoline • avoid stack overflow errors for recursive algorithms • memoization • remember the outcome of previous closure invocations • currying improvements 9
  • 29. Closure annotation @Retention(RetentionPolicy.RUNTIME) @interface Invariant {     Class value() // a closure class }   { @Invariant({ number >= 0 }) class Distance {     float number     String unit }    def d = new Distance(number: 10, unit: "meters")  def anno = Distance.getAnnotation(Invariant) def check = anno.value().newInstance(d, d) assert check(d) 10
  • 30. Closure annotation @Retention(RetentionPolicy.RUNTIME) @interface Invariant {     Class value() // a closure class }   { @Invariant({ number >= 0 }) class Distance {     float number     Poor-m an’s GCont racts String unit }    def d = new Distance(number: 10, unit: "meters")  def anno = Distance.getAnnotation(Invariant) def check = anno.value().newInstance(d, d) assert check(d) 10
  • 32. Closure memoization def plus = { a, b -> sleep 1000; a + b }.memoize() 11
  • 33. Closure memoization def plus = { a, b -> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms 11
  • 34. Closure memoization def plus = { a, b -> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(1, 2) == 3 // return immediately 11
  • 35. Closure memoization def plus = { a, b -> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(1, 2) == 3 // return immediately assert plus(2, 2) == 4 // after 1000ms 11
  • 36. Closure memoization def plus = { a, b -> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(1, 2) == 3 // return immediately assert plus(2, 2) == 4 // after 1000ms assert plus(2, 2) == 4 // return immediately   11
  • 37. Closure memoization def plus = { a, b -> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(1, 2) == 3 // return immediately assert plus(2, 2) == 4 // after 1000ms assert plus(2, 2) == 4 // return immediately     11
  • 38. Closure memoization def plus = { a, b -> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(1, 2) == 3 // return immediately assert plus(2, 2) == 4 // after 1000ms assert plus(2, 2) == 4 // return immediately     // at least 10 invocations cached 11
  • 39. Closure memoization def plus = { a, b -> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(1, 2) == 3 // return immediately assert plus(2, 2) == 4 // after 1000ms assert plus(2, 2) == 4 // return immediately     // at least 10 invocations cached def plusAtLeast = { ... }.memoizeAtLeast(10) 11
  • 40. Closure memoization def plus = { a, b -> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(1, 2) == 3 // return immediately assert plus(2, 2) == 4 // after 1000ms assert plus(2, 2) == 4 // return immediately     // at least 10 invocations cached def plusAtLeast = { ... }.memoizeAtLeast(10)   11
  • 41. Closure memoization def plus = { a, b -> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(1, 2) == 3 // return immediately assert plus(2, 2) == 4 // after 1000ms assert plus(2, 2) == 4 // return immediately     // at least 10 invocations cached def plusAtLeast = { ... }.memoizeAtLeast(10)   // at most 10 invocations cached 11
  • 42. Closure memoization def plus = { a, b -> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(1, 2) == 3 // return immediately assert plus(2, 2) == 4 // after 1000ms assert plus(2, 2) == 4 // return immediately     // at least 10 invocations cached def plusAtLeast = { ... }.memoizeAtLeast(10)   // at most 10 invocations cached def plusAtMost = { ... }.memoizeAtMost(10)  11
  • 43. Closure memoization def plus = { a, b -> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(1, 2) == 3 // return immediately assert plus(2, 2) == 4 // after 1000ms assert plus(2, 2) == 4 // return immediately     // at least 10 invocations cached def plusAtLeast = { ... }.memoizeAtLeast(10)   // at most 10 invocations cached def plusAtMost = { ... }.memoizeAtMost(10)  // between 10 and 20 invocations cached 11
  • 44. Closure memoization def plus = { a, b -> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(1, 2) == 3 // return immediately assert plus(2, 2) == 4 // after 1000ms assert plus(2, 2) == 4 // return immediately     // at least 10 invocations cached def plusAtLeast = { ... }.memoizeAtLeast(10)   // at most 10 invocations cached def plusAtMost = { ... }.memoizeAtMost(10)  // between 10 and 20 invocations cached def plusAtLeast = { ... }.memoizeBetween(10, 20) 11
  • 45. Builtin JSON support • Consuming • Producing • Pretty-printing 12
  • 46. Builtin JSON support import groovy.json.*  def payload = new URL( "http://github.../json/commits/...").text  def slurper = new JsonSlurper() def doc = slurper.parseText(payload)  doc.commits.message.each { println it } 13
  • 47. Builtin JSON support import groovy.json.*    def json = new JsonBuilder()    json.person {     name "Guillaume" age 35     pets "Hector", "Felix" }  println json.toString() 14
  • 48. Builtin JSON support import groovy.json.*    def json = new JsonBuilder()    json.person {     {     name "Guillaume" "person": {         "name": "Guillaume",         age 35     "age": 35,         pets "Hector", "Felix" "pets": [             }  "Hector",             println json.toString() "Felix"         ]     } } 14
  • 49. Builtin JSON support import groovy.json.*    println JsonOutput.prettyPrint( '{"person":{"name":"Guillaume","age":35,' + '"pets":["Hector","Felix"]}}') {     "person": {         "name": "Guillaume",         "age": 35,         "pets": [             "Hector",             "Felix"         ]     } } 15
  • 50. New AST transformations • @Log • Controlling execution • @ThreadInterrupt • @Field • @TimedInterrupt • @ConditionalInterrupt • @AutoClone • @InheritConstructor • @AutoExternalizable • @WithReadLock • @Canonical • @WithWriteLock • @ToString • @EqualsAndHashCode • @TupleConstructor • @ListenerList 16
  • 51. @Log • Four different loggers can be injected •@Log •@Commons import groovy.util.logging.*  •@Log4j   @Log •@Slf4j class Car {     Car() {         log.info 'Car constructed'     • Possible to implement }  } your own strategy   def c = new Car() 17
  • 52. @Log • Four different loggers can be injected •@Log •@Commons import groovy.util.logging.*  •@Log4j   @Log •@Slf4j Guarded w/ an if class Car {     Car() {         log.info 'Car constructed'     • Possible to implement }  } your own strategy   def c = new Car() 17
  • 53. Controlling code execution • Your application may run user’s code •what if the code runs in infinite loops or for too long? •what if the code consumes too many resources? • 3 new transforms at your rescue •@ThreadInterrupt: adds Thread#isInterrupted checks so your executing thread stops when interrupted •@TimedInterrupt: adds checks in method and closure bodies to verify it’s run longer than expected •@ConditionalInterrupt: adds checks with your own conditional logic to break out from the user code 18
  • 54. @ThreadInterrupt @ThreadInterrupt import groovy.transform.ThreadInterrupt    while (true) { // eat lots of CPU } 19
  • 55. @ThreadInterrupt @ThreadInterrupt import groovy.transform.ThreadInterrupt    while (true) { { if (Thread.currentThread().isInterrupted()) throw new InterruptedException() // eat lots of CPU } 19
  • 56. @ToString • Provides a default toString() method to your types • Available annotation options • includeNames, includeFields, includeSuper, excludes import groovy.transform.ToString    @ToString class Person {     String name     int age }    println new Person(name: 'Pete', age: 15) // => Person(Pete, 15) 20
  • 57. @EqualsAndHashCode • Provides default implementations for equals() and hashCode() methods import groovy.transform.EqualsAndHashCode    @EqualsAndHashCode class Coord {     int x, y }    def c1 = new Coord(x: 20, y: 5) def c2 = new Coord(x: 20, y: 5)    assert c1 == c2 assert c1.hashCode() == c2.hashCode() 21
  • 58. @TupleConstructor • Provides a « classical » constructor with all properties • Several annotation parameter options available import groovy.transform.TupleConstructor    @TupleConstructor class Person {     String name     int age }    def m = new Person('Marion', 4)         assert m.name == 'Marion' assert m.age == 4 22
  • 59. @InheritConstructors • Classes like Exception are painful when extended, as all the base constructors should be replicated class CustomException extends Exception { CustomException() { super() } CustomException(String msg) { super(msg) } CustomException(String msg, Throwable t) { super(msg, t) } CustomException(Throwable t) { super(t) } } 23
  • 60. @InheritConstructors • Classes like Exception are painful when extended, as all the base constructors should be replicated import groovy.transform.* @InheritConstructors class CustomException extends Exception { CustomException() { super() } CustomException(String msg) { super(msg) } CustomException(String msg, Throwable t) { super(msg, t) } CustomException(Throwable t) { super(t) } } 23
  • 61. Miscellaneous • Compilation customizers • Java 7 diamond operator • Slashy and dollar slashy strings • New GDK methods • (G)String to Enum coercion • Customizing the Groovysh prompt • Executing remote scripts 24
  • 63. Groovy 2.0 • A more modular Groovy • Java 7 alignements: Project Coin • binary literals • underscore in literals • multicatch • JDK 7: InvokeDynamic • Static type checking • Static compilation 26
  • 64. Groovy Modularity • Groovy’s « all » JAR weighs in at 6 MB • Nobody needs everything • Template engine, Ant scripting, Swing UI building... • Provide a smaller core •and several smaller JARs per feature • Provide hooks for setting up DGM methods, etc. 27
  • 65. The new JARs • A smaller groovy.jar: 3MB • Modules •console • sql •docgenerator • swing •groovydoc • servlet •groovysh • templates •ant • test •bsf • testng •jsr-223 • json •jmx • xml 28
  • 66. Extension modules • Create your own module •contribute instance extension methods package foo class StringExtension { static introduces(String self, String name) { "Hi ${name), I’m ${self}" } } // usage: "Guillaume".introduces("Cédric") 29
  • 67. Extension modules • Create your own module •contribute instance extension methods Same structure as Categories package foo class StringExtension { static introduces(String self, String name) { "Hi ${name), I’m ${self}" } } // usage: "Guillaume".introduces("Cédric") 29
  • 68. Extension modules • Create your own module •contribute class extension methods package foo class StaticStringExtension { static hi(String self) { "Hi!" } } // usage: String.hi() 30
  • 69. Extension module descriptor • Descriptor in: META-INF/services/ org.codehaus.groovy.runtime.ExtensionModule moduleName = stringExtensions moduleVersion = 1.0 // comma-separated list of classes extensionClasses = foo.StringExtension // comma-separated list of classes staticExtensionClasses = foo.StaticStringExtension 31
  • 70. Java 7 / JDK 7 • Project Coin and InvokeDynamic 32
  • 71. Binary literals • We had decimal, octal and hexadecimal notations for number literals • We can now use binary representations too int x = 0b10101111 assert x == 175   byte aByte = 0b00100001 assert aByte == 33   int anInt = 0b1010000101000101 assert anInt == 41285 33
  • 72. Underscore in literals • Now we can also add underscores in number literals for more readability long creditCardNumber = 1234_5678_9012_3456L long socialSecurityNumbers = 999_99_9999L float monetaryAmount = 12_345_132.12 long hexBytes = 0xFF_EC_DE_5E long hexWords = 0xFFEC_DE5E long maxLong = 0x7fff_ffff_ffff_ffffL long alsoMaxLong = 9_223_372_036_854_775_807L long bytes = 0b11010010_01101001_10010100_10010010 34
  • 73. Multicatch • One block for multiple exception caught •rather than duplicating the block try { /* ... */ } catch(IOException | NullPointerException e) { /* one block to treat 2 exceptions */ } 35
  • 74. InvokeDynamic • Groovy 2.0 supports JDK 7’s invokeDynamic • compiler has a flag for compiling against JDK 7 • might use the invokeDynamic backport for < JDK 7 • Benefits • more runtime performance! • at least as fast as current « dynamic » Groovy •in the long run, will allow us to get rid of code! • call site caching, thanks to MethodHandles • metaclass registry, thanks to ClassValues • will let the JIT inline calls more easily 36
  • 75. Static Type Checking • Goal: make the Groovy compiler «grumpy»! • and throw compilation errors (not at runtime) • Not everybody needs dynamic features all the time • think Java libraries scripting • Grumpy should... • tell you about your method or variable typos • complain if you call methods that don’t exist • shout on assignments of wrong types • infer the types of your variables • figure out GDK methods • etc... 37
  • 76. Typos in a variable or import groovy.transform.TypeChecked   void method() {}   @TypeChecked test() { // Cannot find matching method metthhoood() metthhoood()   def name = "Guillaume" // variable naamme is undeclared println naamme } 38
  • 77. Typos in a variable or import groovy.transform.TypeChecked   void method() {}   @TypeChecked test() { // Cannot find matching method metthhoood() metthhoood()   def name = "Guillaume" Compilation // variable naamme is undeclared errors! println naamme } 38
  • 78. Typos in a variable or Annotation can be at class or method level import groovy.transform.TypeChecked   void method() {}   @TypeChecked test() { // Cannot find matching method metthhoood() metthhoood()   def name = "Guillaume" Compilation // variable naamme is undeclared errors! println naamme } 38
  • 79. Wrong assignments // cannot assign value of type... to variable... int x = new Object() Set set = new Object()   def o = new Object() int x = o   String[] strings = ['a','b','c'] int str = strings[0]   // cannot find matching method plus() int i = 0 i += '1' 39
  • 80. Wrong assignments // cannot assign value of type... to variable... int x = new Object() Set set = new Object() Compilation   errors! def o = new Object() int x = o   String[] strings = ['a','b','c'] int str = strings[0]   // cannot find matching method plus() int i = 0 i += '1' 39
  • 81. Wrong return types // checks if/else branch return values @TypeChecked int method() { if (true) { 'String' } else { 42 } } // works for switch/case & try/catch/finally   // transparent toString() implied @TypeChecked String greeting(String name) { def sb = new StringBuilder() sb << "Hi " << name } 40
  • 82. Wrong return types // checks if/else branch return values @TypeChecked int method() { Compilation if (true) { 'String' } error! else { 42 } } // works for switch/case & try/catch/finally   // transparent toString() implied @TypeChecked String greeting(String name) { def sb = new StringBuilder() sb << "Hi " << name } 40
  • 83. Type inference @TypeChecked test() { def name = "  Guillaume  "   // String type infered (even inside GString) println "NAME = ${name.toUpperCase()}"   // Groovy GDK method support // (GDK operator overloading too) println name.trim()   int[] numbers = [1, 2, 3] // Element n is an int for (int n in numbers) { println n } } 41
  • 84. Statically checked & dyn. @TypeChecked String greeting(String name) { // call method with dynamic behavior // but with proper signature generateMarkup(name.toUpperCase()) }   // usual dynamic behavior String generateMarkup(String name) { def sw = new StringWriter() new MarkupBuilder(sw).html { body { div name } } sw.toString() } 42
  • 85. Instanceof checks @TypeChecked void test(Object val) { if (val instanceof String) { println val.toUpperCase() } else if (val instanceof Number) { println "X" * val.intValue() } } 43
  • 86. Instanceof checks No need @TypeChecked for casts void test(Object val) { if (val instanceof String) { println val.toUpperCase() } else if (val instanceof Number) { println "X" * val.intValue() } } 43
  • 87. Instanceof checks No need @TypeChecked for casts void test(Object val) { if (val instanceof String) { println val.toUpperCase() } else if (val instanceof Number) { println "X" * val.intValue() } } Can call String#multiply(int) from the Groovy Development Kit 43
  • 88. Lowest Upper Bound • Represents the lowest « super » type classes have in common •may be virtual (aka « non-denotable ») @TypeChecked test() { // an integer and a BigDecimal return [1234, 3.14] } 44
  • 89. Lowest Upper Bound • Represents the lowest « super » type classes have in common •may be virtual (aka « non-denotable ») @TypeChecked test() { // an integer and a BigDecimal return [1234, 3.14] } Inferred return type: List<Number & Comparable> 44
  • 90. Lowest Upper Bound • Represents the lowest « super » type classes have in common •may be virtual (aka « non-denotable ») @TypeChecked test() { // an integer and a BigDecimal return [1234, 3.14] } Inferred return type: List<Number & Comparable> 44
  • 91. Flow typing • Static type checking shouldn’t complain even for bad coding practicies which work without type checks @TypeChecked test() { def var = 123 // inferred type is int int x = var // var is an int var = "123" // assign var with a String x = var.toInteger() // no problem, no need to cast var = 123 x = var.toUpperCase() // error, var is int! } 45
  • 92. Gotcha: static checking vs • Type checking works at compile-time •adding @TypeChecked doesn’t change behavior • do not confuse with static compilation • Most dynamic features cannot be type checked •metaclass changes, categories •dynamically bound variables (ex: script’s binding) • However, compile-time metaprogramming works •as long as proper type information is defined 46
  • 93. Gotcha: runtime @TypeChecked void test() { Integer.metaClass.foo = {} 123.foo() } 47
  • 94. Gotcha: runtime @TypeChecked void test() { Integer.metaClass.foo = {} 123.foo() } Not allowed: metaClass property is dynamic 47
  • 95. Gotcha: runtime @TypeChecked void test() { Integer.metaClass.foo = {} 123.foo() } Method not Not allowed: recognized metaClass property is dynamic 47
  • 96. Gotcha: explicit type for @TypeChecked test() { ["a", "b", "c"].collect { it.toUpperCase() // Not OK } } • A « Groovy Enhancement Proposal » to address the issue 48
  • 97. Gotcha: explicit type for @TypeChecked test() { ["a", "b", "c"].collect { String it -> it.toUpperCase() // OK, it’s a String } } • A « Groovy Enhancement Proposal » to address the issue 48
  • 98. Closure shared variables @TypeChecked test() { def var = "abc" def cl = { var = new Date() } cl() var.toUpperCase() // Not OK! } 49
  • 99. Closure shared variables var assigned in the closure: «shared closure variable» @TypeChecked test() { def var = "abc" def cl = { var = new Date() } cl() var.toUpperCase() // Not OK! } 49
  • 100. Closure shared variables var assigned in the closure: «shared closure variable» @TypeChecked test() { Impossible to ensure the def var = "abc" assignment def cl = { var = new Date() } really happens cl() var.toUpperCase() // Not OK! } 49
  • 101. Closure shared variables var assigned in the closure: «shared closure variable» @TypeChecked test() { Impossible to ensure the def var = "abc" assignment def cl = { var = new Date() } really happens cl() var.toUpperCase() // Not OK! } Only methods of the most specific compatible type (LUB) are allowed by the type checker 49
  • 102. Closure shared variables class A { void foo() {} } class B extends A { void bar() {} } @TypeChecked test() { def var = new A() def cl = { var = new B() } cl() var.foo() // OK! } 50
  • 103. Closure shared variables class A { void foo() {} } class B extends A { void bar() {} } @TypeChecked test() { def var = new A() def cl = { var = new B() } cl() var.foo() // OK! } var is at least an instance of A 50
  • 104. Static Compilation • Given your Groovy code can be type checked... we can as well compile it « statically » • ie. generate the same byte code as javac • Also interesting for those stuck in JDK < 7 to benefit from performance improvements 51
  • 105. Static Compilation: • You gain: •Type safety • thanks to static type checking • static compilation builds upon static type checking •Faster code • as close as possible to Java’s performance •Code immune to « monkey patching » • metaprogramming badly used can interfere with framework code •Smaller bytecode size 52
  • 106. Static Compilation: • But you loose: • Dynamic features •metaclass changes, categories, etc. • Dynamic method dispatch •although as close as possible to « dynamic » Groovy 53
  • 107. Statically compiled & dyn. @CompileStatic String greeting(String name) { // call method with dynamic behavior // but with proper signature generateMarkup(name.toUpperCase()) }   // usual dynamic behavior String generateMarkup(String name) { def sw = new StringWriter() new MarkupBuilder(sw).html { body { div name } } sw.toString() } 54
  • 108. What about performance? • Comparisons between: • Java • Groovy static compilation (Groovy 2.0) • Groovy with primitive optimizations (Groovy 1.8+) • Groovy without optimizations (Groovy 1.7) 55
  • 109. What about performance? Pi (π) Binary Fibonacci quadrature trees Java 191 ms 97 ms 3.6 s Static 1.7 1.8 2.0 compilation 197 ms 101 ms 4.3 s Primitive optimizations 360 ms 111 ms 23.7 s No prim. optimizations 2590 ms 3220 ms 50.0 s 56
  • 110. Summary • Main themes of the Groovy 2.0 release •Modularity • Embark the JDK 7 enhancements •Project Coin •Invoke Dynamic • Static aspects • Static type checking • Static compilation 57
  • 111. Thank you! ge e Lafor lopment Gu illaum ovy Deve Gro H ead of om ge@ gmail.c Emai l: glafor forge e :@ gla .to/glaforg Twitter : http://gplus spot.com + pp Google p://glaforge.a tt Blog: h 58
  • 112. Questions & Answers • Got questions, really? Q&A 59
  • 113. Image credits • Bugs bunny: http://storage.canalblog.com/63/56/517188/47634843.jpeg • Pills: http://www.we-ew.com/wp-content/uploads/2011/01/plan-b-pills.jpg • Chains: http://2.bp.blogspot.com/-GXDVqUYSCa0/TVdBsON4tdI/AAAAAAAAAW4/EgJOUmAxB28/s1600/breaking-chains5_copy9611.jpg • Slurp: http://www.ohpacha.com/218-532-thickbox/gamelle-slurp.jpg • Grumpy: http://mafeuilledechou.fr/__oneclick_uploads/2010/05/grumpy.jpg • Modularity: http://php.jglobal.com/blog/wp-content/uploads/2009/11/modularity.jpg • Agenda: http://www.plombiereslesbains.fr/images/stories/agenda.jpg • Java 7: http://geeknizer.com/wp-content/uploads/java7.jpg • Road Runner: http://newspaper.li/static/4ada046b7772f0612fec4e3840142308.jpg • Porky: http://joshuadsandy.files.wordpress.com/2011/05/porky-pig-5.jpg • Will E help: http://www.clipart-fr.com/data/clipart/looney/looney_004.jpg • Coyote road runner: http://www.jenkle.com/wp-content/uploads/2010/12/coyote-wallpaper1.jpg • Lube: http://images.motorcycle-superstore.com/ProductImages/OG/0000_Motul_Chain_Lube_Road_--.jpg 60

Notes de l'éditeur

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n
  94. \n
  95. \n
  96. \n
  97. \n
  98. \n
  99. \n
  100. \n
  101. \n
  102. \n
  103. \n
  104. \n
  105. \n
  106. \n
  107. \n
  108. \n
  109. \n
  110. \n
  111. \n
  112. \n
  113. \n
  114. \n
  115. \n
  116. \n
  117. \n
  118. \n
  119. \n
  120. \n
  121. \n
  122. \n
  123. \n
  124. \n
  125. \n
  126. \n
  127. \n
  128. \n
  129. \n
  130. \n