0
Whatʼs new in Groovy 1.8 and beyond?Guillaume LaforgeGroovy Project ManagerSpringSource, a division of VMwareTwitter: @gla...
Guillaume Laforge• Groovy Project Manager at VMware  • Initiator of the Grails framework  • Creator of the Gaelyk toolkit•...
Guillaume Laforge• Groovy Project Manager at VMware  • Initiator of the Grails framework  • Creator of the Gaelyk toolkit•...
Groovy 1.7             @glaforge — http://glaforge.appspot.com   —   http://gplus.to/glaforge   3
Groovy 1.7185             @glaforge — http://glaforge.appspot.com   —   http://gplus.to/glaforge   3
Groovy 1.7185k             @glaforge — http://glaforge.appspot.com   —   http://gplus.to/glaforge   3
Groovy 1.7185k    FIRST MONTH        AFTER RELEASE             @glaforge — http://glaforge.appspot.com   —   http://gplus....
Groovy 1.7                                                            k             @glaforge — http://glaforge.appspot.co...
Groovy 1.7177k    SECOND MONTH        AFTER RELEASE             @glaforge — http://glaforge.appspot.com   —   http://gplus...
Groovy 1.7                                                            k             @glaforge — http://glaforge.appspot.co...
Groovy 1.7362k USERS?             @glaforge — http://glaforge.appspot.com   —   http://gplus.to/glaforge   3
?TIP OFTHEICEBERG
Guesstimate   1/2                                                        Users   Million@glaforge — http://glaforge.appspo...
Agenda         @glaforge — http://glaforge.appspot.com   —   http://gplus.to/glaforge   6
Agenda• Whatʼs new in Groovy 1.8?  – Nicer DSLs with command chains expressions  – Runtime performance improvements  – GPa...
Agenda• Whatʼs new in Groovy 1.8?  – Nicer DSLs with command chains expressions  – Runtime performance improvements  – GPa...
Command chains expressions          @glaforge — http://glaforge.appspot.com   —   http://gplus.to/glaforge   7
Command chains expressions• A grammar improvement allowing you to  drop dots & parens when chaining method calls  – an ext...
Command chains expressions• A grammar improvement allowing you to  drop dots & parens when chaining method calls  – an ext...
Command chains expressions• A grammar improvement allowing you to  drop dots & parens when chaining method calls  – an ext...
Command chains expressions• A grammar improvement allowing you to  drop dots & parens when chaining method calls  – an ext...
Command chains expressions• A grammar improvement allowing you to  drop dots & parens when chaining method calls  – an ext...
Command chains expressions        turn left  then right           @glaforge — http://glaforge.appspot.com   —   http://gpl...
Command chains expressions       Alternation of       method names        turn left  then right              @glaforge — h...
Command chains expressions       Alternation of       method names        turn left  then right                           ...
Command chains expressions        turn left  then right           @glaforge — http://glaforge.appspot.com   —   http://gpl...
Command chains expressions       Equivalent to:            (    ).    (     )        turn left  then right             @gl...
LookM  a!N op are ns,no do ts!
Command chains expressions    Before... we used to do... take 2.pills, of: chloroquinine, after: 6.hours                 @...
Command chains expressions    Before... we used to do... take 2.pills, of: chloroquinine, after: 6.hours    Normal argumen...
Command chains expressions    Before... we used to do... take 2.pills, of: chloroquinine, after: 6.hours    Normal argumen...
Command chains expressions     Before... we used to do... take 2.pills, of: chloroquinine, after: 6.hours     Normal argum...
Command chains expressions     Now, even less punctuation! take 2.pills  of  chloroquinine  after  6.hours                ...
Command chains expressions     Now, even less punctuation!     (       ).   (             ).      (       ) take 2.pills  ...
Command chains expressions      // environment initialization      Integer.metaClass.getPills { ‐> delegate }      Integer...
Command chains expressions take 2.pills  of  chloroquinine  after  6.hours           @glaforge — http://glaforge.appspot.c...
Command chains expressions take 2.pills  of  chloroquinine  after  6.hours                      ... some dots remain ...  ...
Command chains expressions       Yes, we can... get rid of them :-) take 2  pills of  chloroquinine  after  6 hours       ...
Command chains expressions       Yes, we can... get rid of them :-)     ( ).     (  ).              (     ). (     ) take ...
Command chains expressions      // variable injection      def (of, after, hours) = /*...*/             // implementing th...
Command chains expressions          @glaforge — http://glaforge.appspot.com   —   http://gplus.to/glaforge   16
Command chains expressions // methods with multiple arguments (commas)           @glaforge — http://glaforge.appspot.com  ...
Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor          ...
Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // levera...
Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // levera...
Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // levera...
Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // levera...
Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // levera...
Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // levera...
Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // levera...
Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // levera...
Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor     (    ...
Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor     (    ...
Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor     (    ...
Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor     (    ...
Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor     (    ...
Runtime performance improvements• Significant runtime improvements  for primitive type operations  – classical Fibonacci ex...
GPars bundled• GPars is bundled  in the Groovy distribution• GPars covers a wide range of parallel and concurrent  paradig...
Closure enhancements• Closure annotation parameters• Some more functional flavor  – composition  – trampoline  – memoizatio...
Closure annotation parameters    @Retention(RetentionPolicy.RUNTIME)    @interface Invariant {            Class value() //...
Closure annotation parameters    @Retention(RetentionPolicy.RUNTIME)    @interface Invariant {            Class value() //...
Closure composition    def plus2  = { it + 2 }    def times3 = { it * 3 }      {   def times3plus2 = plus2 << times3    as...
Closure trampoline           @glaforge — http://glaforge.appspot.com   —   http://gplus.to/glaforge   22
Closure trampoline def factorial factorial = { int n, BigInteger accu = 1G ‐>                                             ...
Closure memoization           @glaforge — http://glaforge.appspot.com   —   http://gplus.to/glaforge   23
Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize()            @glaforge — http://glaforge.appspot.com ...
Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms            @...
Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(...
Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(...
Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(...
Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(...
Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(...
Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(...
Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(...
Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(...
Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(...
Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(...
Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms assert plus(...
Currying improvements           @glaforge — http://glaforge.appspot.com   —   http://gplus.to/glaforge   24
Currying improvements  // right currying  def divide = { a, b ‐> a / b }  def halver = divide.rcurry(2)  assert halver(8) ...
Currying improvements  // right currying  def divide = { a, b ‐> a / b }  def halver = divide.rcurry(2)  assert halver(8) ...
Builtin JSON support• Consuming• Producing• Pretty-printing                    @glaforge — http://glaforge.appspot.com   —...
Builtin JSON supportimport groovy.json.* def payload = new URL(    "http://github.../json/commits/...").text def slurper =...
Builtin JSON support      import groovy.json.*              def json = new JsonBuilder()              json.person {       ...
Builtin JSON support  import groovy.json.*      println JsonOutput.prettyPrint(      {"person":{"name":"Guillaume","age":3...
Builtin JSON support  import groovy.json.*      println JsonOutput.prettyPrint(      {"person":{"name":"Guillaume","age":3...
New AST transformations• @Log                                        • @Canonical                                         ...
@Log• Four different loggers can be injected  – @Log, @Commons, @Log4j, @Slf4j• Possible to implement your own strategy   ...
@Log• Four different loggers can be injected  – @Log, @Commons, @Log4j, @Slf4j• Possible to implement your own strategy   ...
@Field• Surprising scoping rules in scripts  – variables are local to the run() method  – variables arenʼt visible in meth...
Controlling code execution• Your application may run userʼs code  – what if the code runs in infinite loops or for too long...
Controlling code execution• Your application may run userʼs code  – what if the code runs in infinite loops or for too long...
Controlling code execution• Your application may run userʼs code  – what if the code runs in infinite loops or for too long...
Controlling code execution• Your application may run userʼs code  – what if the code runs in infinite loops or for too long...
@ThreadInterrupt     @ThreadInterrupt     import groovy.transform.ThreadInterrupt            while (true) {         // eat...
@ThreadInterrupt      @ThreadInterrupt      import groovy.transform.ThreadInterrupt              while (true) {  {       i...
@ThreadInterrupt       @ThreadInterrupt       import groovy.transform.ThreadInterrupt                while (true) {   {   ...
@TimedInterrupt       @TimedInterrupt(10)       import groovy.transform.TimedInterrupt                while (true) {      ...
@ConditionalInterrupt• Specify your own condition to be inserted  at the start of method and closure bodies  – check for a...
@ToString• Provides a default toString() method to your types• Available annotation options  – includeNames, includeFields...
@EqualsAndHashCode• Provides default implementations for equals() and  hashCode() methods          import groovy.transform...
@TupleConstructor• Provides a «classical» constructor with all properties• Several annotation parameter options available ...
@Canonical• One annotation to rule them all!  – @Canonical mixes together    • @ToString    • @EqualsAndHashCode    • @Tup...
@InheritConstructor• Classes like Exception are painful when extended, as all  the base constructors should be replicatedc...
@InheritConstructor• Classes like Exception are painful when extended, as all  the base constructors should be replicatedi...
@WithReadLock, @WithWriteLock import groovy.transform.*    class ResourceProvider {         private final Map<String, Stri...
@WithReadLock, @WithWriteLock    import groovy.transform.*          class ResourceProvider {            private final Map<...
Miscelanous•   Compilation customizers•   Java 7 diamond operator•   Slashy and dollar slashy strings•   New GDK methods• ...
Compilation customizers• Ability to apply some customization to the Groovy  compilation process• Three available customize...
Imports customizer def configuration = new CompilerConfiguration()   def custo = new ImportCustomizer() custo.addStaticSta...
Applying an AST transformation    def configuration = new CompilerConfiguration()    configuration.addCompilationCustomize...
Secure AST customizer             Idea: Implement an «arithmetic shell»               Being able control what a user scrip...
Secure AST customizer ... secure.with {   // disallow closure creation   closuresAllowed = false    // disallow method def...
Secure AST customizer...   // language tokens allowed   tokensWhitelist = [      PLUS, MINUS, MULTIPLY, DIVIDE, MOD, POWER...
Secure AST customizer• Ready to evaluate our arithmetic expressions!    ...    def config = new CompilerConfiguration()   ...
Slashy and dollar slashy strings• Slashy strings are now multiline  – particularly handy for multi-line regexs• Dollar sla...
New GDK methods         @glaforge — http://glaforge.appspot.com   —   http://gplus.to/glaforge   51
New GDK methods   // count              @glaforge — http://glaforge.appspot.com   —   http://gplus.to/glaforge   51
New GDK methods   // count   assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5             @glaforge — http://glaforge...
New GDK methods   // count   assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5                 @glaforge — http://glaf...
New GDK methods   // count   assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5       // count by             @glaforge...
New GDK methods   // count   assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5       // count by   assert [0:2, 1:3] =...
New GDK methods   // count   assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5       // count by   assert [0:2, 1:3] =...
New GDK methods   // count   assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5       // count by   assert [0:2, 1:3] =...
New GDK methods   // count   assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5       // count by   assert [0:2, 1:3] =...
New GDK methods   // count   assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5       // count by   assert [0:2, 1:3] =...
New GDK methods   // count   assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5       // count by   assert [0:2, 1:3] =...
New GDK methods   // count   assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5       // count by   assert [0:2, 1:3] =...
New GDK methods   // count   assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5       // count by   assert [0:2, 1:3] =...
New GDK methods   // count   assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5       // count by   assert [0:2, 1:3] =...
New GDK methods   // count   assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5       // count by   assert [0:2, 1:3] =...
New GDK methods   // count   assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5       // count by   assert [0:2, 1:3] =...
New GDK methods   // count   assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5       // count by   assert [0:2, 1:3] =...
(G)String to Enum coercion           @glaforge — http://glaforge.appspot.com   —   http://gplus.to/glaforge   52
(G)String to Enum coercion         enum Color {               @glaforge — http://glaforge.appspot.com   —   http://gplus.t...
(G)String to Enum coercion         enum Color {                 red, green, blue           @glaforge — http://glaforge.app...
(G)String to Enum coercion         enum Color {                 red, green, blue         }            @glaforge — http://g...
(G)String to Enum coercion         enum Color {                 red, green, blue         }                      @glaforge ...
(G)String to Enum coercion         enum Color {                 red, green, blue         }                    // coercion ...
(G)String to Enum coercion         enum Color {                 red, green, blue         }                    // coercion ...
(G)String to Enum coercion         enum Color {                 red, green, blue         }                    // coercion ...
(G)String to Enum coercion         enum Color {                 red, green, blue         }                    // coercion ...
(G)String to Enum coercion         enum Color {                 red, green, blue         }                    // coercion ...
(G)String to Enum coercion         enum Color {                 red, green, blue         }                    // coercion ...
(G)String to Enum coercion         enum Color {                 red, green, blue         }                    // coercion ...
(G)String to Enum coercion         enum Color {                 red, green, blue         }                    // coercion ...
Customizing the Groovysh prompt           @glaforge — http://glaforge.appspot.com   —   http://gplus.to/glaforge   53
Launching remote scripts• With the Groovy command, you can launch remote scripts > groovy http://groovyconsole.appspot.com...
What’scookingfor 1.9?
Groovy 1.9 roadmap• Java 7 alignements: Project Coin    – binary literals    – underscore in literals    – multicatch•   J...
Groovy 1.9 roadmap• Java 7 alignements: Project Coin    – binary literals    – underscore in literals    – multicatch•   J...
Java 7 / JDK 7• Project Coin and InvokeDynamic              @glaforge — http://glaforge.appspot.com   —   http://gplus.to/...
Binary literals• We had decimal, octal and hexadecimal notations  for number literals• We can now use binary representatio...
Underscore in literals• Now we can also add underscores  in number literals for more readability   long creditCardNumber =...
Multicatch• One block for multiple exception caught  – rather than duplicating the block   try {       /* ... */   } catch...
InvokeDynamic• Groovy 1.9 will support JDK 7ʼs invokeDynamic  – an «indy» branch started recently  – compiler will have a ...
Groovy Modularity• Groovyʼs «all» JAR weighs in at 4MB• Nobody needs everything  – Template engine, Ant scripting, Swing U...
Static Type Checking• Goal: make the Groovy compiler «grumpy»!  – and throw compilation errors (not at runtime)• Not every...
A typo in your variable or method namesimport groovy.transform.StaticTypes void method() {} @TypeChecked test() {    // Ca...
A typo in your variable or method namesimport groovy.transform.StaticTypes void method() {} @TypeChecked test() {    // Ca...
Complain on wrong assignments// cannot assign value of type... to variable...int x = new Object()Set set = new Object() de...
Complain on wrong assignments// cannot assign value of type... to variable...int x = new Object()Set set = new Object()   ...
Complain on wrong return typesString method() { String }// cannot assign value of type String...int x = method()// checks ...
Complain on wrong return typesString method() { String }// cannot assign value of type String...int x = method()          ...
Type inference    @TypeChecked test() {        def name = "  Guillaume  "             // String type infered (even inside ...
Staticly checked method & dynamic method       @TypeChecked       String greeting(String name) {           // call method ...
Bytecode viewer• Groovy Consoleʼs  bytecode viewer  from the AST  browser window  – select class    generation phase  – se...
Disable Global AST transformations// witout a specific configuration, the AST builder worksdef shell = new GroovyShell()sh...
Summary          @glaforge — http://glaforge.appspot.com                                                    ROCKS!        ...
Thank you!                                e                        L aforg pment               aume vy Develo         Guil...
Q&A — Got questions, Really?
Image credits•   Iceberg: http://hqworld.net/gallery/data/media/20/tip_of_the_iceberg.jpg•   Bicycle: http://drunkcyclist....
Upcoming SlideShare
Loading in...5
×

Groovy Update - Guillaume Laforge - Greach 2011

1,765

Published on

Overview of the features of Groovy 1.8 and what is coming in the next major version.

Published in: Technology, Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,765
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
38
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "Groovy Update - Guillaume Laforge - Greach 2011"

  1. 1. Whatʼs new in Groovy 1.8 and beyond?Guillaume LaforgeGroovy Project ManagerSpringSource, a division of VMwareTwitter: @glaforgeBlog: http://glaforge.appspot.comGoogle+: http://gplus.to/glaforge
  2. 2. Guillaume Laforge• Groovy Project Manager at VMware • Initiator of the Grails framework • Creator of the Gaelyk toolkit• Co-author of Groovy in Action• Speaking worldwide w/ a French accent• Follow me on... • My blog: http://glaforge.appspot.com • Twitter: @glaforge • Google+: http://gplus.to/glaforge @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 2
  3. 3. Guillaume Laforge• Groovy Project Manager at VMware • Initiator of the Grails framework • Creator of the Gaelyk toolkit• Co-author of Groovy in Action• Speaking worldwide w/ a French accent• Follow me on... • My blog: http://glaforge.appspot.com • Twitter: @glaforge • Google+: http://gplus.to/glaforge @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 2
  4. 4. Groovy 1.7 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 3
  5. 5. Groovy 1.7185 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 3
  6. 6. Groovy 1.7185k @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 3
  7. 7. Groovy 1.7185k FIRST MONTH AFTER RELEASE @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 3
  8. 8. Groovy 1.7 k @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 3
  9. 9. Groovy 1.7177k SECOND MONTH AFTER RELEASE @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 3
  10. 10. Groovy 1.7 k @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 3
  11. 11. Groovy 1.7362k USERS? @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 3
  12. 12. ?TIP OFTHEICEBERG
  13. 13. Guesstimate 1/2 Users Million@glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 5
  14. 14. Agenda @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 6
  15. 15. Agenda• Whatʼs new in Groovy 1.8? – Nicer DSLs with command chains expressions – Runtime performance improvements – GPars bundled for taming your multicores – Closure enhancements – Builtin JSON support – New AST transformations @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 6
  16. 16. Agenda• Whatʼs new in Groovy 1.8? – Nicer DSLs with command chains expressions – Runtime performance improvements – GPars bundled for taming your multicores – Closure enhancements – Builtin JSON support – New AST transformations• Whatʼs cooking for Groovy 1.9? – Continued runtime performance improvements – Alignments with JDK 7 • Project Coin (small language changes) • Static type checking • InvokeDynamic @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 6
  17. 17. Command chains expressions @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 7
  18. 18. Command chains expressions• A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 7
  19. 19. Command chains expressions• A grammar improvement allowing you to drop dots & parens when chaining method calls – an extended version of top-level statements like println @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 7
  20. 20. Command chains expressions• 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) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 7
  21. 21. Command chains expressions• 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) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 7
  22. 22. Command chains expressions• 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)• Letʼs have a look at some examples @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 7
  23. 23. Command chains expressions  turn left  then right  @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 8
  24. 24. Command chains expressions Alternation of method names  turn left  then right  @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 8
  25. 25. Command chains expressions Alternation of method names  turn left  then right  and parameters (even named ones) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 8
  26. 26. Command chains expressions  turn left  then right  @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 8
  27. 27. Command chains expressions Equivalent to:      (    ).    (     )  turn left  then right  @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 8
  28. 28. LookM a!N op are ns,no do ts!
  29. 29. Command chains expressions Before... we used to do... take 2.pills, of: chloroquinine, after: 6.hours @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 10
  30. 30. Command chains expressions Before... we used to do... take 2.pills, of: chloroquinine, after: 6.hours Normal argument @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 10
  31. 31. Command chains expressions Before... we used to do... take 2.pills, of: chloroquinine, after: 6.hours Normal argument Named arguments @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 10
  32. 32. Command chains expressions Before... we used to do... take 2.pills, of: chloroquinine, after: 6.hours Normal argument Named arguments Woud call: def take(Map m, Quantity q) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 10
  33. 33. Command chains expressions Now, even less punctuation! take 2.pills  of  chloroquinine  after  6.hours @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 11
  34. 34. Command chains expressions Now, even less punctuation!     (       ).   (             ).      (       ) take 2.pills  of  chloroquinine  after  6.hours @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 11
  35. 35. Command chains expressions // environment initialization Integer.metaClass.getPills { ‐> delegate } Integer.metaClass.getHours { ‐> delegate }   // variable injection def chloroquinine = /*...*/   { } // implementing the DSL logic def take(n) {     [of: { drug ‐>         [after: { time ‐> /*...*/ }]     }] } // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ take 2.pills of chloroquinine after 6.hours @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 12
  36. 36. Command chains expressions take 2.pills  of  chloroquinine  after  6.hours @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 13
  37. 37. Command chains expressions take 2.pills  of  chloroquinine  after  6.hours ... some dots remain ... @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 13
  38. 38. Command chains expressions Yes, we can... get rid of them :-) take 2  pills of  chloroquinine  after  6 hours @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 14
  39. 39. Command chains expressions Yes, we can... get rid of them :-)     ( ).     (  ).              (     ). (     ) take 2  pills of  chloroquinine  after  6 hours @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 14
  40. 40. Command chains expressions // variable injection def (of, after, hours) = /*...*/   // implementing the DSL logic { } def take(n) {     [pills: { of ‐>         [chloroquinine: { after ‐>             [6: { time ‐> }]         }]     }] } // ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ take 2 pills of chloroquinine after 6 hours @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 15
  41. 41. Command chains expressions @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  42. 42. Command chains expressions // methods with multiple arguments (commas) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  43. 43. Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  44. 44. Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // leverage named‐args as punctuation @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  45. 45. Command chains expressions // methods with multiple arguments (commas) take coffee  with sugar, milk  and liquor // leverage named‐args as punctuation check that: margarita  tastes good @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  46. 46. Command chains expressions // 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  47. 47. Command chains expressions // 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 {} @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  48. 48. Command chains expressions // 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  49. 49. Command chains expressions // 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  50. 50. Command chains expressions // 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  51. 51. Command chains expressions // 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  52. 52. Command chains expressions // 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  53. 53. Command chains expressions // 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  54. 54. Command chains expressions // 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  55. 55. Command chains expressions // 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  56. 56. Command chains expressions // 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     ( ). @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 16
  57. 57. Runtime performance improvements• Significant runtime improvements for primitive type operations – classical Fibonacci example x13 faster! – almost as fast as Java• Some direct method calls on this @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 17
  58. 58. 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, STM – parallel arrays, executors, and more... @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 18
  59. 59. Closure enhancements• Closure annotation parameters• Some more functional flavor – composition – trampoline – memoization• Currying improvements @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 19
  60. 60. Closure annotation parameters @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) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 20
  61. 61. Closure annotation parameters @Retention(RetentionPolicy.RUNTIME) @interface Invariant {         Class value() // a closure class }  { @Invariant({ number >= 0 }) class Distance {         float number     an’s G Cont racts     String unit P oor-m }    def d = new Distance(number: 10, unit: "meters")  def anno = Distance.getAnnotation(Invariant) def check = anno.value().newInstance(d, d) assert check(d) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 20
  62. 62. Closure composition def plus2  = { it + 2 } def times3 = { it * 3 }   { def times3plus2 = plus2 << times3 assert times3plus2(3) == 11 assert times3plus2(4) == plus2(times3(4))   { def plus2times3 = times3 << plus2 assert plus2times3(3) == 15 assert plus2times3(5) == times3(plus2(5))    // reverse composition{ assert times3plus2(3) == (times3 >> plus2)(3) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 21
  63. 63. Closure trampoline @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 22
  64. 64. Closure trampoline def factorial factorial = { int n, BigInteger accu = 1G ‐>        if (n < 2) return accu          factorial.trampoline(n ‐ 1, n * accu) }.trampoline()   assert factorial(1)    == 1 assert factorial(3)    == 1 * 2 * 3 assert factorial(1000) == 402387260... @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 22
  65. 65. Closure memoization @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 23
  66. 66. Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 23
  67. 67. Closure memoization def plus = { a, b ‐> sleep 1000; a + b }.memoize() assert plus(1, 2) == 3 // after 1000ms @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 23
  68. 68. 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 23
  69. 69. 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 23
  70. 70. 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   @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 23
  71. 71. 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     @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 23
  72. 72. 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 23
  73. 73. 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) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 23
  74. 74. 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)   @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 23
  75. 75. 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 23
  76. 76. 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)  @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 23
  77. 77. 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 23
  78. 78. 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) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 23
  79. 79. Currying improvements @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 24
  80. 80. Currying improvements // right currying def divide = { a, b ‐> a / b } def halver = divide.rcurry(2) assert halver(8) == 4     @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 24
  81. 81. Currying improvements // right currying def divide = { a, b ‐> a / b } def halver = divide.rcurry(2) assert halver(8) == 4     // currying n‐th parameter def joinWithSeparator =      { one, sep, two ‐> one + sep + two } def joinWithComma =      joinWithSeparator.ncurry(1, , ) assert joinWithComma(a, b) == a, b @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 24
  82. 82. Builtin JSON support• Consuming• Producing• Pretty-printing @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 25
  83. 83. Builtin JSON supportimport 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 } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 26
  84. 84. Builtin JSON support import groovy.json.*    def json = new JsonBuilder()    json.person {         name "Guillaume"     age 33         pets "Hector", "Felix" }  println json.toString() @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 27
  85. 85. Builtin JSON support import groovy.json.*    println JsonOutput.prettyPrint(     {"person":{"name":"Guillaume","age":33, +      "pets":["Hector","Felix"]}})   @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 28
  86. 86. Builtin JSON support import groovy.json.*    println JsonOutput.prettyPrint(     {"person":{"name":"Guillaume","age":33, +      "pets":["Hector","Felix"]}})   {         "person": {                 "name": "Guillaume",              "age": 33,                 "pets": [                         "Hector",                         "Felix"                 ]         } } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 28
  87. 87. New AST transformations• @Log • @Canonical – @ToString,• @Field – @EqualsAndHashCode, – @TupleConstructor• @AutoClone• @AutoExternalizable • @InheritConstructor • @WithReadLock• Controlling the execution of your code • @WithWriteLock – @ThreadInterrupt, – @TimedInterrupt, • @ListenerList – @ConditionalInterrupt @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 29
  88. 88. @Log• Four different loggers can be injected – @Log, @Commons, @Log4j, @Slf4j• Possible to implement your own strategy import groovy.util.logging.*    @Log class Car {         Car() {                 log.info Car constructed         } }    def c = new Car() @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 30
  89. 89. @Log• Four different loggers can be injected – @Log, @Commons, @Log4j, @Slf4j• Possible to implement your own strategy import groovy.util.logging.*    @Log class Car {     Guarded     Car() {         w/ an if         log.info Car constructed         } }    def c = new Car() @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 30
  90. 90. @Field• Surprising scoping rules in scripts – variables are local to the run() method – variables arenʼt visible in methods • although visually the variable is in a surrounding scope• @Field creates a field in the script class @Field List awe = [1, 2, 3] def awesum() { awe.sum() } assert awesum() == 6 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 31
  91. 91. 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? @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 32
  92. 92. 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 32
  93. 93. 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 32
  94. 94. 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• Also see compilation customizers later on @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 32
  95. 95. @ThreadInterrupt @ThreadInterrupt import groovy.transform.ThreadInterrupt    while (true) {     // eat lots of CPU } 33 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 33
  96. 96. @ThreadInterrupt @ThreadInterrupt import groovy.transform.ThreadInterrupt    while (true) { {     if (Thread.currentThread.isInterrupted())         throw new InterruptedException() }     // eat lots of CPU } 33 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 33
  97. 97. @ThreadInterrupt @ThreadInterrupt import groovy.transform.ThreadInterrupt    while (true) { {     if (Thread.currentThread.isInterrupted())         throw new InterruptedException() }     // eat lots of CPU }• Two optional annotation parameters available – checkOnMethodStart (true by default) – applyToAllClasses (true by default) 33 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 33
  98. 98. @TimedInterrupt @TimedInterrupt(10) import groovy.transform.TimedInterrupt    while (true) {     // eat lots of CPU }• InterruptedException thrown when checks indicate code ran longer than desired• Optional annotation parameters available – same as @ThreadInterrupt – value: for an amount of time duration – unit: for the time duration unit (TimeUnit.SECONDS) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 34
  99. 99. @ConditionalInterrupt• Specify your own condition to be inserted at the start of method and closure bodies – check for available resources, number of times run, etc.• Leverages closure annotation parameters from Groovy 1.8 @ConditionalInterrupt({ counter++ > 2 }) import groovy.transform.ConditionalInterrupt import groovy.transform.Field    @Field int counter = 0  100.times {         println executing script method... } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 35
  100. 100. @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) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 36
  101. 101. @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() @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 37
  102. 102. @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, 3)         assert m.name == Marion assert m.age  == 3 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 38
  103. 103. @Canonical• One annotation to rule them all! – @Canonical mixes together • @ToString • @EqualsAndHashCode • @TupleConstructor• You can customize behavior by combining @Canonical and one of the other annotations @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 39
  104. 104. @InheritConstructor• Classes like Exception are painful when extended, as all the base constructors should be replicatedclass CustomException extends Exception {    CustomException()                        { super()       }    CustomException(String msg)              { super(msg)    }    CustomException(String msg, Throwable t) { super(msg, t) }    CustomException(Throwable t)             { super(t)      }} @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 40
  105. 105. @InheritConstructor• Classes like Exception are painful when extended, as all the base constructors should be replicatedimport groovy.transform.*@InheritConstructorsclass CustomException extends Exception {    CustomException()                        { super()       }    CustomException(String msg)              { super(msg)    }    CustomException(String msg, Throwable t) { super(msg, t) }    CustomException(Throwable t)             { super(t)      }} @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 40
  106. 106. @WithReadLock, @WithWriteLock import groovy.transform.*    class ResourceProvider {         private final Map<String, String> data = new HashMap<>()       @WithReadLock         String getResource(String key) {                 return data.get(key)         }            @WithWriteLock         void refresh() {                 //reload the resources into memory         } } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 41
  107. 107. @WithReadLock, @WithWriteLock import groovy.transform.*    class ResourceProvider {         private final Map<String, String> data = new HashMap<>()  {     @WithReadLock         String getResource(String key) {                 return data.get(key)         }       {     @WithWriteLock         void refresh() {                 //reload the resources into memory         } } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 41
  108. 108. Miscelanous• Compilation customizers• Java 7 diamond operator• Slashy and dollar slashy strings• New GDK methods• (G)String to Enum coercion @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 42
  109. 109. Compilation customizers• Ability to apply some customization to the Groovy compilation process• Three available customizers – ImportCustomizer – ASTTransformationCustomizer – SecureASTCustomizer• But you can implement your own @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 43
  110. 110. Imports customizer def configuration = new CompilerConfiguration()   def custo = new ImportCustomizer() custo.addStaticStar(Math.name) configuration.addCompilationCustomizers(custo)    def result = new GroovyShell(configuration)     .evaluate(" cos PI/3 ") @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 44
  111. 111. Applying an AST transformation def configuration = new CompilerConfiguration() configuration.addCompilationCustomizers(     new ASTTransformationCustomizer(Log))    new GroovyShell(configuration).evaluate("""     class Car {                 Car() {                         log.info Car constructed                 }         }          log.info Constructing a car         def c = new Car() """) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 45
  112. 112. Secure AST customizer Idea: Implement an «arithmetic shell» Being able control what a user script is allowed to do: only arithmetic expressions• Letʼs setup our environment – some imports – an import customizer to import java.lang.Math.* – prepare a secure AST customizerimport org.codehaus.groovy.control.customizers.*import org.codehaus.groovy.control.*import static org.codehaus.groovy.syntax.Types.* def imports = new ImportCustomizer().addStaticStars(java.lang.Math)def secure = new SecureASTCustomizer() @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 46
  113. 113. Secure AST customizer ... secure.with { // disallow closure creation closuresAllowed = false  // disallow method definitions methodDefinitionAllowed = false    // empty white list => forbid imports importsWhitelist = []  staticImportsWhitelist = [] // only allow the java.lang.Math.* static import staticStarImportsWhitelist = [java.lang.Math ... @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 47
  114. 114. Secure AST customizer... // language tokens allowed tokensWhitelist = [ PLUS, MINUS, MULTIPLY, DIVIDE, MOD, POWER, PLUS_PLUS,  MINUS_MINUS, COMPARE_EQUAL, COMPARE_NOT_EQUAL,  COMPARE_LESS_THAN, COMPARE_LESS_THAN_EQUAL,  COMPARE_GREATER_THAN, COMPARE_GREATER_THAN_EQUAL ]  // types allowed to be used (including primitive types) constantTypesClassesWhiteList = [ Integer, Float, Long, Double, BigDecimal,  Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE ]  // classes who are allowed to be receivers of method calls receiversClassesWhiteList = [  Math, Integer, Float, Double, Long, BigDecimal ]}... @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 48
  115. 115. Secure AST customizer• Ready to evaluate our arithmetic expressions! ... def config = new CompilerConfiguration() config.addCompilationCustomizers(imports, secure) def shell = new GroovyShell(config)   shell.evaluate cos PI/3• But the following would have failed: shell.evaluate System.exit(0) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 49
  116. 116. Slashy and dollar slashy strings• Slashy strings are now multiline – particularly handy for multi-line regexs• Dollar slashy string notation introduced – a multiline GString with different escaping rules def (name, date) = ["Guillaume", "Oct, 26th"] def dollarSlashy = $/         Hello $name, today were ${date}     $ dollar‐sign         $$ dollar‐sign          backslash         / slash        $/ slash /$  @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 50
  117. 117. New GDK methods @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 51
  118. 118. New GDK methods // count @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 51
  119. 119. New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 51
  120. 120. New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5   @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 51
  121. 121. New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5   // count by @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 51
  122. 122. New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5   // count by assert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 51
  123. 123. New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5   // count by assert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 } assert [(true):2, (false):4]      == Groovy.toList().countBy{ it == o } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 51
  124. 124. New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5   // count by assert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 } assert [(true):2, (false):4]      == Groovy.toList().countBy{ it == o }   @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 51
  125. 125. New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5   // count by assert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 } assert [(true):2, (false):4]      == Groovy.toList().countBy{ it == o }   // min/max for maps with closures @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 51
  126. 126. New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5   // count by assert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 } assert [(true):2, (false):4]      == Groovy.toList().countBy{ it == o }   // min/max for maps with closures def map = [a: 1, bbb: 4, cc: 5, dddd: 2]  @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 51
  127. 127. New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5   // count by assert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 } assert [(true):2, (false):4]      == Groovy.toList().countBy{ it == o }   // min/max for maps with closures def map = [a: 1, bbb: 4, cc: 5, dddd: 2]  assert map.max { it.key.size() }.key == dddd @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 51
  128. 128. New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5   // count by assert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 } assert [(true):2, (false):4]      == Groovy.toList().countBy{ it == o }   // min/max for maps with closures def map = [a: 1, bbb: 4, cc: 5, dddd: 2]  assert map.max { it.key.size() }.key == dddd assert map.min { it.value }.value == 1 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 51
  129. 129. New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5   // count by assert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 } assert [(true):2, (false):4]      == Groovy.toList().countBy{ it == o }   // min/max for maps with closures def map = [a: 1, bbb: 4, cc: 5, dddd: 2]  assert map.max { it.key.size() }.key == dddd assert map.min { it.value }.value == 1   @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 51
  130. 130. New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5   // count by assert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 } assert [(true):2, (false):4]      == Groovy.toList().countBy{ it == o }   // min/max for maps with closures def map = [a: 1, bbb: 4, cc: 5, dddd: 2]  assert map.max { it.key.size() }.key == dddd assert map.min { it.value }.value == 1   // map withDefault() @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 51
  131. 131. New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5   // count by assert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 } assert [(true):2, (false):4]      == Groovy.toList().countBy{ it == o }   // min/max for maps with closures def map = [a: 1, bbb: 4, cc: 5, dddd: 2]  assert map.max { it.key.size() }.key == dddd assert map.min { it.value }.value == 1   // map withDefault() def words = "one two two three three three".split() @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 51
  132. 132. New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5   // count by assert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 } assert [(true):2, (false):4]      == Groovy.toList().countBy{ it == o }   // min/max for maps with closures def map = [a: 1, bbb: 4, cc: 5, dddd: 2]  assert map.max { it.key.size() }.key == dddd assert map.min { it.value }.value == 1   // map withDefault() def words = "one two two three three three".split() def freq = [:].withDefault { k ‐> 0 } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 51
  133. 133. New GDK methods // count assert [2,4,2,1,3,5,2,4,3].count { it % 2 == 0 } == 5   // count by assert [0:2, 1:3] == [1,2,3,4,5].countBy{ it % 2 } assert [(true):2, (false):4]      == Groovy.toList().countBy{ it == o }   // min/max for maps with closures def map = [a: 1, bbb: 4, cc: 5, dddd: 2]  assert map.max { it.key.size() }.key == dddd assert map.min { it.value }.value == 1   // map withDefault() def words = "one two two three three three".split() def freq = [:].withDefault { k ‐> 0 } words.each { freq[it] += 1 } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 51
  134. 134. (G)String to Enum coercion @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
  135. 135. (G)String to Enum coercion enum Color {     @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
  136. 136. (G)String to Enum coercion enum Color {         red, green, blue @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
  137. 137. (G)String to Enum coercion enum Color {         red, green, blue }  @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
  138. 138. (G)String to Enum coercion enum Color {         red, green, blue }    @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
  139. 139. (G)String to Enum coercion enum Color {         red, green, blue }    // coercion with as @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
  140. 140. (G)String to Enum coercion enum Color {         red, green, blue }    // coercion with as def r = "red" as Color  @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
  141. 141. (G)String to Enum coercion enum Color {         red, green, blue }    // coercion with as def r = "red" as Color    @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
  142. 142. (G)String to Enum coercion enum Color {         red, green, blue }    // coercion with as def r = "red" as Color    // implicit coercion @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
  143. 143. (G)String to Enum coercion enum Color {         red, green, blue }    // coercion with as def r = "red" as Color    // implicit coercion Color b = "blue"  @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
  144. 144. (G)String to Enum coercion enum Color {         red, green, blue }    // coercion with as def r = "red" as Color    // implicit coercion Color b = "blue"    @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
  145. 145. (G)String to Enum coercion enum Color {         red, green, blue }    // coercion with as def r = "red" as Color    // implicit coercion Color b = "blue"    // with GStrings too @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
  146. 146. (G)String to Enum coercion enum Color {         red, green, blue }    // coercion with as def r = "red" as Color    // implicit coercion Color b = "blue"    // with GStrings too def g = "${green}" as Color @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 52
  147. 147. Customizing the Groovysh prompt @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 53
  148. 148. Launching remote scripts• With the Groovy command, you can launch remote scripts > groovy http://groovyconsole.appspot.com/raw/110001• Be careful to what youʼre executing :-) @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 54
  149. 149. What’scookingfor 1.9?
  150. 150. Groovy 1.9 roadmap• Java 7 alignements: Project Coin – binary literals – underscore in literals – multicatch• JDK 7: InvokeDynamic• Towards a more modular Groovy• Static type checking and compilation• Miscelanous• What else? Your call! @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 56
  151. 151. Groovy 1.9 roadmap• Java 7 alignements: Project Coin – binary literals – underscore in literals – multicatch• JDK 7: InvokeDynamic• Towards a more modular Groovy• Static type checking and compilation• Miscelanous• What else? Your call! @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 56
  152. 152. Java 7 / JDK 7• Project Coin and InvokeDynamic @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 57
  153. 153. 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 58
  154. 154. 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 59
  155. 155. Multicatch• One block for multiple exception caught – rather than duplicating the block try {     /* ... */ } catch(IOException | NullPointerException e) {     /* one block to treat 2 exceptions */ } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 60
  156. 156. InvokeDynamic• Groovy 1.9 will support JDK 7ʼs invokeDynamic – an «indy» branch started recently – compiler will have a flag for compiling against JDK 7• Benefits – more runtime performance! – 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 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 61
  157. 157. Groovy Modularity• Groovyʼs «all» JAR weighs in at 4MB• 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 EMCs / DGM methods, etc. @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 62
  158. 158. 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... @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 63
  159. 159. A typo in your variable or method namesimport groovy.transform.StaticTypes void method() {} @TypeChecked test() {    // Cannot find matching method metthhoood()    metthhoood()     def name = "Guillaume"    // variable naamme is undeclared    println naamme} @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 64
  160. 160. A typo in your variable or method namesimport groovy.transform.StaticTypes void method() {} @TypeChecked test() {    // Cannot find matching method metthhoood()    metthhoood()     def name = "Guillaume"    // variable naamme is undeclared Compilation    println naamme errors!} @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 64
  161. 161. Complain on 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 = 0i += 1 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 65
  162. 162. Complain on 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 = 0i += 1 @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 65
  163. 163. Complain on wrong return typesString method() { String }// cannot assign value of type String...int x = method()// checks if/else branch return valuesint method() {    if (true) { String }    else { 42 }}// works for switch/case & try/catch/finally // transparent toString() impliedString greeting(String name) {    def sb = new StringBuilder()    sb << "Hi" << name} @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 66
  164. 164. Complain on wrong return typesString method() { String }// cannot assign value of type String...int x = method() Compilation errors!// checks if/else branch return valuesint method() {    if (true) { String }    else { 42 }}// works for switch/case & try/catch/finally // transparent toString() impliedString greeting(String name) {    def sb = new StringBuilder()    sb << "Hi" << name} @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 66
  165. 165. 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     } } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 67
  166. 166. Staticly checked method & dynamic method @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() } @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 68
  167. 167. Bytecode viewer• Groovy Consoleʼs bytecode viewer from the AST browser window – select class generation phase – select a class node @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 69
  168. 168. Disable Global AST transformations// witout a specific configuration, the AST builder worksdef shell = new GroovyShell()shell.evaluate(script) // passesdef config = new CompilerConfiguration()config.disabledGlobalASTTransformations =    [org.codehaus.groovy.ast.builder.AstBuilderTransformation]def script =     import org.codehaus.groovy.ast.builder.AstBuilder    new AstBuilder().buildFromCode { "Hello" } // now with the configuration in place,// the AST builder transform is not appliedshell = new GroovyShell(config) // <‐‐ with the configurationshouldFail {    shell.evaluate(script) // fails} @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 70
  169. 169. Summary @glaforge — http://glaforge.appspot.com ROCKS! — http://gplus.to/glaforge 71
  170. 170. Thank you! e L aforg pment aume vy Develo Guill Groo m Hea d of g mail.co aforge@ mail: gl glaforge e E @ o /glaforg T witter : http://gplus.t Go ogle+: @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 72
  171. 171. Q&A — Got questions, Really?
  172. 172. Image credits• Iceberg: http://hqworld.net/gallery/data/media/20/tip_of_the_iceberg.jpg• Bicycle: http://drunkcyclist.com/gallery/main.php?g2_view=core.DownloadItem&g2_itemId=2131&g2_serialNumber=2• 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• Cooking: http://www.flickr.com/photos/eole/449958332/sizes/l/• Oui nide iou: http://desencyclopedie.wikia.com/wiki/Fichier:Superdupont_we_need_you.jpg• Guitar: http://www.lelitteraire.com/IMG/breveon323.jpg• Trampoline: http://www.fitness-online.fr/images/trampoline-1-m.jpg• Curry: http://www.pot-a-epices.com/wp-content/uploads/2009/02/curry1.jpg• Slurp: http://www.ohpacha.com/218-532-thickbox/gamelle-slurp.jpg• Caution: http://www.jeunes-epinay-sur-seine.fr/wp-content/uploads/2010/11/caution-colocation.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• WIP: http://www.connetport.com/wp-content/uploads/Work_in_progress.svg_.png• Grumpy 2: http://grumpy.division-par-zero.fr/wp-content/images/grumpy.jpg• @glaforge — http://glaforge.appspot.com — http://gplus.to/glaforge 74
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×