SlideShare uma empresa Scribd logo
1 de 34
Baixar para ler offline
Given Groovy Who Needs Java?

                                 Prof Russel Winder
                                  http://www.russel.org.uk

                                  email: russel@winder.org.uk
                                 xmpp: russel@winder.org.uk
                                    twitter: @russel_winder




Copyright © 2012 Russel Winder                                  1
Interstitial Advertisement




Copyright © 2012 Russel Winder                        2
Introduction




Copyright © 2012 Russel Winder                  3
Groovy was…
     ●   …designed to be a dynamic symbiote to Java.

     ●   Java is statically typed.
     ●   Groovy is optionally typed.




Copyright © 2012 Russel Winder                         4
Groovy was…
     ●   …designed to have a very lightweight syntax.

     ●   Literal syntax for lists and maps.
     ●   As little punctuation as possible.




Copyright © 2012 Russel Winder                          5
Groovy was…
     ●   …designed to work with code as first class entity.

     ●   Closures and functional approach from the outset.
     ●   No waiting for Java 8.




Copyright © 2012 Russel Winder                                6
Code




Copyright © 2012 Russel Winder          7
println 'Hello World.'




Copyright © 2012 Russel Winder                            8
public class testAll_GroovyTestCase extends GroovyTestCase {
  void test_helloWorld_trivial() {
     assert 'helloWorld_trivial.groovy'.execute().text == 'Hello World.n'
  }
}




                                 Power asserts


                                                 JUnit3 behind the scenes

Copyright © 2012 Russel Winder                                              9
@Grab('org.spockframework:spock:0.7-groovy2.0')
   import spock.lang.Specification

   class TestAll_Spock extends Specification {
      def "ensure the hello world program prints hello world"() {
        expect:
           'helloWorld_trivial.groovy'.execute().text == 'Hello World.n'
      }
   }




Copyright © 2012 Russel Winder                                              10
def datum = ['Hello', ' ', 'World', '.'].join('')

                   println datum




Copyright © 2012 Russel Winder                                         11
String datum = ['Hello', ' ', 'World', '.'].join('')

                   println datum




Copyright © 2012 Russel Winder                                            12
datum = ['Hello', ' ', 'World', '.'].join('')

                   println datum




Copyright © 2012 Russel Winder                                     13
words = [:]

                             words.third = 'World'
                             words << [first: 'Hello', fourth: '.']
                             words['second'] = ' '

                             sequence = ['first', 'second', 'third', 'fourth']

                             println(sequence.collect{words[it]}.join(''))




Copyright © 2012 Russel Winder                                                   14
@GrabResolver(name='atlassian',
    root='https://maven.atlassian.com/content/groups/public/')
  @Grab('org.swift.tools:gint:1.5.0')
  import org.swift.tools.Gint

  includeTool << Gint

  gint.initialize(this)

  new File('.').eachFileMatch(~/helloWorld_.*.groovy/) {
    gint.add(name: it.name, inline: { it.name.execute().text == 'Hello World.n' })
  }

  gint.finalizeTest()




Copyright © 2012 Russel Winder                                                        15
import groovy.xml.MarkupBuilder

                                 new MarkupBuilder().html{
                                   head{
                                     title 'Hello World.'
                                   }
                                   body{
                                     (0 ..< 3).each {
                                        em('Hello')
                                     }
                                   }
                                 }




Copyright © 2012 Russel Winder                                     16
<html>
                                   <head>
                                     <title>Hello World.</title>
                                   </head>
                                   <body>
                                     <em>Hello</em>
                                     <em>Hello</em>
                                     <em>Hello</em>
                                   </body>
                                 </html>




Copyright © 2012 Russel Winder                                     17
html = new XmlParser().parse(System.in)
                       assert html.head.title.text() == 'Hello World.'
                       assert html.body.em.text() == 'HelloHelloHello'




Copyright © 2012 Russel Winder                                           18
import javax.swing.WindowConstants

         import groovy.swing.SwingBuilder

         def widget = new SwingBuilder().frame(
            title: 'Hello World Window',
            size: [200, 100],
            defaultCloseOperation: WindowConstants.EXIT_ON_CLOSE
         ){
            panel {
              button(text:'Say Hello', actionPerformed: { println 'Hello.' })
            }
         }
         widget.show()




Copyright © 2012 Russel Winder                                                  19
Copyright © 2012 Russel Winder   20
final n = 100000
                 final delta = 1.0 / n
                 final startTime = System.nanoTime()
                 def sum = 0.0
                 for (i in 1 .. n) { sum += 1 / (1 + ((i - 0.5) * delta) ** 2) }
                 final pi = 4 * delta * sum
                 final elapseTime = (System.nanoTime() - startTime) / 1e9
                 Output.out(getClass().name, pi, n, elapseTime)




Copyright © 2012 Russel Winder                                                     21
final int n = 1000000000
              final double delta = 1.0 / n
              final startTimeNanos = System.nanoTime()
              double sum = 0.0
              for (int i = 1; i <= n; ++i) {
                 final double x = (i - 0.5d) * delta
                 sum += 1.0d / (1.0d + x * x)
              }
              final double pi = 4.0 * delta * sum
              final elapseTime = (System.nanoTime() - startTimeNanos) / 1e9
              Output.out(getClass().name, pi, n, elapseTime)




Copyright © 2012 Russel Winder                                                22
import groovy.transform.CompileStatic

           @CompileStatic execute() {
             final int n = 1000000000
             final double delta = 1.0 / n
             final startTimeNanos = System.nanoTime ()
             double sum = 0.0
             for (int i = 1; i <= n; ++i) {
                final double x = (i - 0.5d) * delta
                sum += 1.0d / (1.0d + x * x)
             }
             final double pi = 4.0 * delta * sum
             final elapseTime = (System.nanoTime() - startTimeNanos) / 1e9
             Output.out(getClass().name, pi, n, elapseTime)
           }

           execute()
Copyright © 2012 Russel Winder                                               23
final int n = 10000000
                   final double delta = 1.0 / n
                   final startTime = System.nanoTime()
                   final double pi = 4.0 * delta * (1i .. n).sum {int i ->
                     final double x = (i - 0.5d) * delta
                     1.0d / (1.0d + x * x)
                   }
                   final elapseTime = (System.nanoTime() - startTime) / 1e9
                   Output.out(getClass().name, pi, n, elapseTime)




Copyright © 2012 Russel Winder                                                24
import groovy.transform.CompileStatic

                   @CompileStatic execute() {
                     final int n = 10000000
                     final double delta = 1.0 / n
                     final startTime = System.nanoTime()
                     final double pi = 4.0 * delta * (double)((1i .. n).sum {int i ->
                        final double x = (i - 0.5d) * delta
                        1.0d / (1.0d + x * x)
                     })
                     final elapseTime = (System.nanoTime() - startTime) / 1e9
                     Output.out(getClass().name, pi, n, elapseTime)
                   }

                   execute()



Copyright © 2012 Russel Winder                                                          25
import groovyx.gpars.ParallelEnhancer

                  void execute(final numberOfTasks) {
                    final n = 1000000000
                    final delta = 1.0 / n
                    final startTimeNanos = System.nanoTime ()
                    final sliceSize = (int)(n / numberOfTasks)
                    final items = 0 ..< numberOfTasks
                    ParallelEnhancer.enhanceInstance(items)
                    final pi = 4.0 * delta * items.collectParallel {taskId ->
                      PartialSum.dynamicCompile(taskId, sliceSize, delta)
                    }.sumParallel()
                    final elapseTime = (System.nanoTime() - startTimeNanos) / 1e9
                    Output.out(getClass().name, pi, n, elapseTime, numberOfTasks)
                  }

                  execute 1
                  execute 2
                  execute 8
                  execute 32


Copyright © 2012 Russel Winder                                                      26
static double dynamicCompile(final int taskId, final int sliceSize, final double delta) {
        final int start = 1i + taskId * sliceSize
        final int end = (taskId + 1i) * sliceSize
        double sum = 0.0d
        for (int i = start; i <= end; ++i) {
          final double x = (i - 0.5d) * delta
          sum += 1.0d / (1.0d + x * x)
        }
        sum
      }




Copyright © 2012 Russel Winder                                                                27
Conclusion




Copyright © 2012 Russel Winder                28
There is nothing that Java can do

                        that Groovy cannot do better.




Copyright © 2012 Russel Winder                          29
Interstitial Advertisement




Copyright © 2012 Russel Winder                        30
Given Groovy Who Needs Java?

                                 Prof Russel Winder
                                  http://www.russel.org.uk

                                  email: russel@winder.org.uk
                                 xmpp: russel@winder.org.uk
                                    twitter: @russel_winder




Copyright © 2012 Russel Winder                                  31
Challenge




Copyright © 2012 Russel Winder               32
Problem


                                                        Groovy
                 Java



                                   Develop faster
                                   Execute faster
                                   Can be done at all



Copyright © 2012 Russel Winder                                   33
Given Groovy Who Needs Java?

                                 Prof Russel Winder
                                  http://www.russel.org.uk

                                  email: russel@winder.org.uk
                                 xmpp: russel@winder.org.uk
                                    twitter: @russel_winder




Copyright © 2012 Russel Winder                                  34

Mais conteúdo relacionado

Mais procurados

JCConf 2015 - 輕鬆學google的雲端開發 - Google App Engine入門(上)
JCConf 2015  - 輕鬆學google的雲端開發 - Google App Engine入門(上)JCConf 2015  - 輕鬆學google的雲端開發 - Google App Engine入門(上)
JCConf 2015 - 輕鬆學google的雲端開發 - Google App Engine入門(上)Simon Su
 
Vielseitiges In-Memory Computing mit Apache Ignite und Kubernetes
Vielseitiges In-Memory Computing mit Apache Ignite und KubernetesVielseitiges In-Memory Computing mit Apache Ignite und Kubernetes
Vielseitiges In-Memory Computing mit Apache Ignite und KubernetesQAware GmbH
 
MySQL flexible schema and JSON for Internet of Things
MySQL flexible schema and JSON for Internet of ThingsMySQL flexible schema and JSON for Internet of Things
MySQL flexible schema and JSON for Internet of ThingsAlexander Rubin
 
The Ring programming language version 1.5.3 book - Part 78 of 184
The Ring programming language version 1.5.3 book - Part 78 of 184The Ring programming language version 1.5.3 book - Part 78 of 184
The Ring programming language version 1.5.3 book - Part 78 of 184Mahmoud Samir Fayed
 
ドキュメントデータベースとして MySQLを使う!? ~MySQL JSON UDF~
ドキュメントデータベースとして MySQLを使う!? ~MySQL JSON UDF~ドキュメントデータベースとして MySQLを使う!? ~MySQL JSON UDF~
ドキュメントデータベースとして MySQLを使う!? ~MySQL JSON UDF~yoyamasaki
 
Php user groupmemcached
Php user groupmemcachedPhp user groupmemcached
Php user groupmemcachedJason Anderson
 
The Ring programming language version 1.3 book - Part 51 of 88
The Ring programming language version 1.3 book - Part 51 of 88The Ring programming language version 1.3 book - Part 51 of 88
The Ring programming language version 1.3 book - Part 51 of 88Mahmoud Samir Fayed
 
The Ring programming language version 1.4.1 book - Part 16 of 31
The Ring programming language version 1.4.1 book - Part 16 of 31The Ring programming language version 1.4.1 book - Part 16 of 31
The Ring programming language version 1.4.1 book - Part 16 of 31Mahmoud Samir Fayed
 
The Ring programming language version 1.7 book - Part 51 of 196
The Ring programming language version 1.7 book - Part 51 of 196The Ring programming language version 1.7 book - Part 51 of 196
The Ring programming language version 1.7 book - Part 51 of 196Mahmoud Samir Fayed
 
Understanding Source Code Differences by Separating Refactoring Effects
Understanding Source Code Differences by Separating Refactoring EffectsUnderstanding Source Code Differences by Separating Refactoring Effects
Understanding Source Code Differences by Separating Refactoring EffectsShinpei Hayashi
 
Architecture Components In Real Life Season 2
Architecture Components In Real Life Season 2Architecture Components In Real Life Season 2
Architecture Components In Real Life Season 2Somkiat Khitwongwattana
 
MongoDB: Optimising for Performance, Scale & Analytics
MongoDB: Optimising for Performance, Scale & AnalyticsMongoDB: Optimising for Performance, Scale & Analytics
MongoDB: Optimising for Performance, Scale & AnalyticsServer Density
 
IPC: AIDL is sexy, not a curse
IPC: AIDL is sexy, not a curseIPC: AIDL is sexy, not a curse
IPC: AIDL is sexy, not a curseYonatan Levin
 
Ipc: aidl sexy, not a curse
Ipc: aidl sexy, not a curseIpc: aidl sexy, not a curse
Ipc: aidl sexy, not a curseYonatan Levin
 
concurrency gpars
concurrency gparsconcurrency gpars
concurrency gparsPaul King
 
Di web tech mail (no subject)
Di web tech mail   (no subject)Di web tech mail   (no subject)
Di web tech mail (no subject)shubhamvcs
 
Android Architecture Component in Real Life
Android Architecture Component in Real LifeAndroid Architecture Component in Real Life
Android Architecture Component in Real LifeSomkiat Khitwongwattana
 
Python memory management_v2
Python memory management_v2Python memory management_v2
Python memory management_v2Jeffrey Clark
 
Optimizing Slow Queries with Indexes and Creativity
Optimizing Slow Queries with Indexes and CreativityOptimizing Slow Queries with Indexes and Creativity
Optimizing Slow Queries with Indexes and CreativityMongoDB
 

Mais procurados (20)

JCConf 2015 - 輕鬆學google的雲端開發 - Google App Engine入門(上)
JCConf 2015  - 輕鬆學google的雲端開發 - Google App Engine入門(上)JCConf 2015  - 輕鬆學google的雲端開發 - Google App Engine入門(上)
JCConf 2015 - 輕鬆學google的雲端開發 - Google App Engine入門(上)
 
Di and Dagger
Di and DaggerDi and Dagger
Di and Dagger
 
Vielseitiges In-Memory Computing mit Apache Ignite und Kubernetes
Vielseitiges In-Memory Computing mit Apache Ignite und KubernetesVielseitiges In-Memory Computing mit Apache Ignite und Kubernetes
Vielseitiges In-Memory Computing mit Apache Ignite und Kubernetes
 
MySQL flexible schema and JSON for Internet of Things
MySQL flexible schema and JSON for Internet of ThingsMySQL flexible schema and JSON for Internet of Things
MySQL flexible schema and JSON for Internet of Things
 
The Ring programming language version 1.5.3 book - Part 78 of 184
The Ring programming language version 1.5.3 book - Part 78 of 184The Ring programming language version 1.5.3 book - Part 78 of 184
The Ring programming language version 1.5.3 book - Part 78 of 184
 
ドキュメントデータベースとして MySQLを使う!? ~MySQL JSON UDF~
ドキュメントデータベースとして MySQLを使う!? ~MySQL JSON UDF~ドキュメントデータベースとして MySQLを使う!? ~MySQL JSON UDF~
ドキュメントデータベースとして MySQLを使う!? ~MySQL JSON UDF~
 
Php user groupmemcached
Php user groupmemcachedPhp user groupmemcached
Php user groupmemcached
 
The Ring programming language version 1.3 book - Part 51 of 88
The Ring programming language version 1.3 book - Part 51 of 88The Ring programming language version 1.3 book - Part 51 of 88
The Ring programming language version 1.3 book - Part 51 of 88
 
The Ring programming language version 1.4.1 book - Part 16 of 31
The Ring programming language version 1.4.1 book - Part 16 of 31The Ring programming language version 1.4.1 book - Part 16 of 31
The Ring programming language version 1.4.1 book - Part 16 of 31
 
The Ring programming language version 1.7 book - Part 51 of 196
The Ring programming language version 1.7 book - Part 51 of 196The Ring programming language version 1.7 book - Part 51 of 196
The Ring programming language version 1.7 book - Part 51 of 196
 
Understanding Source Code Differences by Separating Refactoring Effects
Understanding Source Code Differences by Separating Refactoring EffectsUnderstanding Source Code Differences by Separating Refactoring Effects
Understanding Source Code Differences by Separating Refactoring Effects
 
Architecture Components In Real Life Season 2
Architecture Components In Real Life Season 2Architecture Components In Real Life Season 2
Architecture Components In Real Life Season 2
 
MongoDB: Optimising for Performance, Scale & Analytics
MongoDB: Optimising for Performance, Scale & AnalyticsMongoDB: Optimising for Performance, Scale & Analytics
MongoDB: Optimising for Performance, Scale & Analytics
 
IPC: AIDL is sexy, not a curse
IPC: AIDL is sexy, not a curseIPC: AIDL is sexy, not a curse
IPC: AIDL is sexy, not a curse
 
Ipc: aidl sexy, not a curse
Ipc: aidl sexy, not a curseIpc: aidl sexy, not a curse
Ipc: aidl sexy, not a curse
 
concurrency gpars
concurrency gparsconcurrency gpars
concurrency gpars
 
Di web tech mail (no subject)
Di web tech mail   (no subject)Di web tech mail   (no subject)
Di web tech mail (no subject)
 
Android Architecture Component in Real Life
Android Architecture Component in Real LifeAndroid Architecture Component in Real Life
Android Architecture Component in Real Life
 
Python memory management_v2
Python memory management_v2Python memory management_v2
Python memory management_v2
 
Optimizing Slow Queries with Indexes and Creativity
Optimizing Slow Queries with Indexes and CreativityOptimizing Slow Queries with Indexes and Creativity
Optimizing Slow Queries with Indexes and Creativity
 

Semelhante a Given Groovy Who Needs Java

Closures, the next "Big Thing" in Java: Russel Winder
Closures, the next "Big Thing" in Java: Russel WinderClosures, the next "Big Thing" in Java: Russel Winder
Closures, the next "Big Thing" in Java: Russel WinderJAX London
 
Closures: The Next "Big Thing" In Java
Closures: The Next "Big Thing" In JavaClosures: The Next "Big Thing" In Java
Closures: The Next "Big Thing" In JavaRussel Winder
 
Spocktacular Testing - Russel Winder
Spocktacular Testing - Russel WinderSpocktacular Testing - Russel Winder
Spocktacular Testing - Russel WinderJAXLondon2014
 
Spocktacular Testing
Spocktacular TestingSpocktacular Testing
Spocktacular TestingRussel Winder
 
Spocktacular testing
Spocktacular testingSpocktacular testing
Spocktacular testingRussel Winder
 
Android and the Seven Dwarfs from Devox'15
Android and the Seven Dwarfs from Devox'15Android and the Seven Dwarfs from Devox'15
Android and the Seven Dwarfs from Devox'15Murat Yener
 
GPars: Parallelism the Right Way
GPars: Parallelism the Right WayGPars: Parallelism the Right Way
GPars: Parallelism the Right WayRussel Winder
 
Realm Java 2.2.0: Build better apps, faster apps
Realm Java 2.2.0: Build better apps, faster appsRealm Java 2.2.0: Build better apps, faster apps
Realm Java 2.2.0: Build better apps, faster appsSavvycom Savvycom
 
Groovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume Laforge
Groovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume LaforgeGroovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume Laforge
Groovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume LaforgeGuillaume Laforge
 
Gradleintroduction 111010130329-phpapp01
Gradleintroduction 111010130329-phpapp01Gradleintroduction 111010130329-phpapp01
Gradleintroduction 111010130329-phpapp01Tino Isnich
 
Java9 Beyond Modularity - Java 9 más allá de la modularidad
Java9 Beyond Modularity - Java 9 más allá de la modularidadJava9 Beyond Modularity - Java 9 más allá de la modularidad
Java9 Beyond Modularity - Java 9 más allá de la modularidadDavid Gómez García
 
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017 Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017 Codemotion
 
.NET Coding Standards For The Real World (2012)
.NET Coding Standards For The Real World (2012).NET Coding Standards For The Real World (2012)
.NET Coding Standards For The Real World (2012)David McCarter
 
Node.js in action
Node.js in actionNode.js in action
Node.js in actionSimon Su
 

Semelhante a Given Groovy Who Needs Java (20)

Closures, the next "Big Thing" in Java: Russel Winder
Closures, the next "Big Thing" in Java: Russel WinderClosures, the next "Big Thing" in Java: Russel Winder
Closures, the next "Big Thing" in Java: Russel Winder
 
Closures: The Next "Big Thing" In Java
Closures: The Next "Big Thing" In JavaClosures: The Next "Big Thing" In Java
Closures: The Next "Big Thing" In Java
 
Spocktacular Testing - Russel Winder
Spocktacular Testing - Russel WinderSpocktacular Testing - Russel Winder
Spocktacular Testing - Russel Winder
 
Spocktacular Testing
Spocktacular TestingSpocktacular Testing
Spocktacular Testing
 
Spocktacular testing
Spocktacular testingSpocktacular testing
Spocktacular testing
 
Android and the Seven Dwarfs from Devox'15
Android and the Seven Dwarfs from Devox'15Android and the Seven Dwarfs from Devox'15
Android and the Seven Dwarfs from Devox'15
 
GPars: Parallelism the Right Way
GPars: Parallelism the Right WayGPars: Parallelism the Right Way
GPars: Parallelism the Right Way
 
ChtiJUG - Cassandra 2.0
ChtiJUG - Cassandra 2.0ChtiJUG - Cassandra 2.0
ChtiJUG - Cassandra 2.0
 
Realm Java 2.2.0: Build better apps, faster apps
Realm Java 2.2.0: Build better apps, faster appsRealm Java 2.2.0: Build better apps, faster apps
Realm Java 2.2.0: Build better apps, faster apps
 
Realm Java 2.2.0: Build better apps, faster apps
Realm Java 2.2.0: Build better apps, faster appsRealm Java 2.2.0: Build better apps, faster apps
Realm Java 2.2.0: Build better apps, faster apps
 
Introduction to Groovy
Introduction to GroovyIntroduction to Groovy
Introduction to Groovy
 
Terrific Frontends
Terrific FrontendsTerrific Frontends
Terrific Frontends
 
Groovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume Laforge
Groovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume LaforgeGroovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume Laforge
Groovy: to Infinity and Beyond -- JavaOne 2010 -- Guillaume Laforge
 
Gradle Introduction
Gradle IntroductionGradle Introduction
Gradle Introduction
 
Gradleintroduction 111010130329-phpapp01
Gradleintroduction 111010130329-phpapp01Gradleintroduction 111010130329-phpapp01
Gradleintroduction 111010130329-phpapp01
 
From render() to DOM
From render() to DOMFrom render() to DOM
From render() to DOM
 
Java9 Beyond Modularity - Java 9 más allá de la modularidad
Java9 Beyond Modularity - Java 9 más allá de la modularidadJava9 Beyond Modularity - Java 9 más allá de la modularidad
Java9 Beyond Modularity - Java 9 más allá de la modularidad
 
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017 Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
Davide Cerbo - Kotlin: forse è la volta buona - Codemotion Milan 2017
 
.NET Coding Standards For The Real World (2012)
.NET Coding Standards For The Real World (2012).NET Coding Standards For The Real World (2012)
.NET Coding Standards For The Real World (2012)
 
Node.js in action
Node.js in actionNode.js in action
Node.js in action
 

Mais de Russel Winder

On Concurrency and Parallelism in the JVMverse
On Concurrency and Parallelism in the JVMverseOn Concurrency and Parallelism in the JVMverse
On Concurrency and Parallelism in the JVMverseRussel Winder
 
The Case for Kotlin and Ceylon
The Case for Kotlin and CeylonThe Case for Kotlin and Ceylon
The Case for Kotlin and CeylonRussel Winder
 
On the Architectures of Microservices: the next layer
On the Architectures of Microservices: the next layerOn the Architectures of Microservices: the next layer
On the Architectures of Microservices: the next layerRussel Winder
 
Fast Python? Don't Bother
Fast Python? Don't BotherFast Python? Don't Bother
Fast Python? Don't BotherRussel Winder
 
Making Python computations fast
Making Python computations fastMaking Python computations fast
Making Python computations fastRussel Winder
 
Tales from the Workshops
Tales from the WorkshopsTales from the Workshops
Tales from the WorkshopsRussel Winder
 
Making Computations Execute Very Quickly
Making Computations Execute Very QuicklyMaking Computations Execute Very Quickly
Making Computations Execute Very QuicklyRussel Winder
 
Java is Dead, Long Live Ceylon, Kotlin, etc
Java is Dead,  Long Live Ceylon, Kotlin, etcJava is Dead,  Long Live Ceylon, Kotlin, etc
Java is Dead, Long Live Ceylon, Kotlin, etcRussel Winder
 
Java is dead, long live Scala, Kotlin, Ceylon, etc.
Java is dead, long live Scala, Kotlin, Ceylon, etc.Java is dead, long live Scala, Kotlin, Ceylon, etc.
Java is dead, long live Scala, Kotlin, Ceylon, etc.Russel Winder
 
Is Groovy static or dynamic
Is Groovy static or dynamicIs Groovy static or dynamic
Is Groovy static or dynamicRussel Winder
 
Java is dead, long live Scala Kotlin Ceylon etc.
Java is dead, long live Scala Kotlin Ceylon etc.Java is dead, long live Scala Kotlin Ceylon etc.
Java is dead, long live Scala Kotlin Ceylon etc.Russel Winder
 
Dataflow: the concurrency/parallelism architecture you need
Dataflow: the concurrency/parallelism architecture you needDataflow: the concurrency/parallelism architecture you need
Dataflow: the concurrency/parallelism architecture you needRussel Winder
 
Are Go and D threats to Python
Are Go and D threats to PythonAre Go and D threats to Python
Are Go and D threats to PythonRussel Winder
 
Is Groovy as fast as Java
Is Groovy as fast as JavaIs Groovy as fast as Java
Is Groovy as fast as JavaRussel Winder
 
Who needs C++ when you have D and Go
Who needs C++ when you have D and GoWho needs C++ when you have D and Go
Who needs C++ when you have D and GoRussel Winder
 
Java 8: a New Beginning
Java 8: a New BeginningJava 8: a New Beginning
Java 8: a New BeginningRussel Winder
 
Why Go is an important programming language
Why Go is an important programming languageWhy Go is an important programming language
Why Go is an important programming languageRussel Winder
 
GPars: Groovy Parallelism for Java
GPars: Groovy Parallelism for JavaGPars: Groovy Parallelism for Java
GPars: Groovy Parallelism for JavaRussel Winder
 

Mais de Russel Winder (20)

On Concurrency and Parallelism in the JVMverse
On Concurrency and Parallelism in the JVMverseOn Concurrency and Parallelism in the JVMverse
On Concurrency and Parallelism in the JVMverse
 
The Case for Kotlin and Ceylon
The Case for Kotlin and CeylonThe Case for Kotlin and Ceylon
The Case for Kotlin and Ceylon
 
On the Architectures of Microservices: the next layer
On the Architectures of Microservices: the next layerOn the Architectures of Microservices: the next layer
On the Architectures of Microservices: the next layer
 
Fast Python? Don't Bother
Fast Python? Don't BotherFast Python? Don't Bother
Fast Python? Don't Bother
 
Making Python computations fast
Making Python computations fastMaking Python computations fast
Making Python computations fast
 
Tales from the Workshops
Tales from the WorkshopsTales from the Workshops
Tales from the Workshops
 
Making Computations Execute Very Quickly
Making Computations Execute Very QuicklyMaking Computations Execute Very Quickly
Making Computations Execute Very Quickly
 
Java is Dead, Long Live Ceylon, Kotlin, etc
Java is Dead,  Long Live Ceylon, Kotlin, etcJava is Dead,  Long Live Ceylon, Kotlin, etc
Java is Dead, Long Live Ceylon, Kotlin, etc
 
GPars Remoting
GPars RemotingGPars Remoting
GPars Remoting
 
Java is dead, long live Scala, Kotlin, Ceylon, etc.
Java is dead, long live Scala, Kotlin, Ceylon, etc.Java is dead, long live Scala, Kotlin, Ceylon, etc.
Java is dead, long live Scala, Kotlin, Ceylon, etc.
 
GPars 2014
GPars 2014GPars 2014
GPars 2014
 
Is Groovy static or dynamic
Is Groovy static or dynamicIs Groovy static or dynamic
Is Groovy static or dynamic
 
Java is dead, long live Scala Kotlin Ceylon etc.
Java is dead, long live Scala Kotlin Ceylon etc.Java is dead, long live Scala Kotlin Ceylon etc.
Java is dead, long live Scala Kotlin Ceylon etc.
 
Dataflow: the concurrency/parallelism architecture you need
Dataflow: the concurrency/parallelism architecture you needDataflow: the concurrency/parallelism architecture you need
Dataflow: the concurrency/parallelism architecture you need
 
Are Go and D threats to Python
Are Go and D threats to PythonAre Go and D threats to Python
Are Go and D threats to Python
 
Is Groovy as fast as Java
Is Groovy as fast as JavaIs Groovy as fast as Java
Is Groovy as fast as Java
 
Who needs C++ when you have D and Go
Who needs C++ when you have D and GoWho needs C++ when you have D and Go
Who needs C++ when you have D and Go
 
Java 8: a New Beginning
Java 8: a New BeginningJava 8: a New Beginning
Java 8: a New Beginning
 
Why Go is an important programming language
Why Go is an important programming languageWhy Go is an important programming language
Why Go is an important programming language
 
GPars: Groovy Parallelism for Java
GPars: Groovy Parallelism for JavaGPars: Groovy Parallelism for Java
GPars: Groovy Parallelism for Java
 

Último

Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 

Último (20)

Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 

Given Groovy Who Needs Java

  • 1. Given Groovy Who Needs Java? Prof Russel Winder http://www.russel.org.uk email: russel@winder.org.uk xmpp: russel@winder.org.uk twitter: @russel_winder Copyright © 2012 Russel Winder 1
  • 4. Groovy was… ● …designed to be a dynamic symbiote to Java. ● Java is statically typed. ● Groovy is optionally typed. Copyright © 2012 Russel Winder 4
  • 5. Groovy was… ● …designed to have a very lightweight syntax. ● Literal syntax for lists and maps. ● As little punctuation as possible. Copyright © 2012 Russel Winder 5
  • 6. Groovy was… ● …designed to work with code as first class entity. ● Closures and functional approach from the outset. ● No waiting for Java 8. Copyright © 2012 Russel Winder 6
  • 7. Code Copyright © 2012 Russel Winder 7
  • 8. println 'Hello World.' Copyright © 2012 Russel Winder 8
  • 9. public class testAll_GroovyTestCase extends GroovyTestCase { void test_helloWorld_trivial() { assert 'helloWorld_trivial.groovy'.execute().text == 'Hello World.n' } } Power asserts JUnit3 behind the scenes Copyright © 2012 Russel Winder 9
  • 10. @Grab('org.spockframework:spock:0.7-groovy2.0') import spock.lang.Specification class TestAll_Spock extends Specification { def "ensure the hello world program prints hello world"() { expect: 'helloWorld_trivial.groovy'.execute().text == 'Hello World.n' } } Copyright © 2012 Russel Winder 10
  • 11. def datum = ['Hello', ' ', 'World', '.'].join('') println datum Copyright © 2012 Russel Winder 11
  • 12. String datum = ['Hello', ' ', 'World', '.'].join('') println datum Copyright © 2012 Russel Winder 12
  • 13. datum = ['Hello', ' ', 'World', '.'].join('') println datum Copyright © 2012 Russel Winder 13
  • 14. words = [:] words.third = 'World' words << [first: 'Hello', fourth: '.'] words['second'] = ' ' sequence = ['first', 'second', 'third', 'fourth'] println(sequence.collect{words[it]}.join('')) Copyright © 2012 Russel Winder 14
  • 15. @GrabResolver(name='atlassian', root='https://maven.atlassian.com/content/groups/public/') @Grab('org.swift.tools:gint:1.5.0') import org.swift.tools.Gint includeTool << Gint gint.initialize(this) new File('.').eachFileMatch(~/helloWorld_.*.groovy/) { gint.add(name: it.name, inline: { it.name.execute().text == 'Hello World.n' }) } gint.finalizeTest() Copyright © 2012 Russel Winder 15
  • 16. import groovy.xml.MarkupBuilder new MarkupBuilder().html{ head{ title 'Hello World.' } body{ (0 ..< 3).each { em('Hello') } } } Copyright © 2012 Russel Winder 16
  • 17. <html>   <head>     <title>Hello World.</title>   </head>   <body>     <em>Hello</em>     <em>Hello</em>     <em>Hello</em>   </body> </html> Copyright © 2012 Russel Winder 17
  • 18. html = new XmlParser().parse(System.in) assert html.head.title.text() == 'Hello World.' assert html.body.em.text() == 'HelloHelloHello' Copyright © 2012 Russel Winder 18
  • 19. import javax.swing.WindowConstants import groovy.swing.SwingBuilder def widget = new SwingBuilder().frame( title: 'Hello World Window', size: [200, 100], defaultCloseOperation: WindowConstants.EXIT_ON_CLOSE ){ panel { button(text:'Say Hello', actionPerformed: { println 'Hello.' }) } } widget.show() Copyright © 2012 Russel Winder 19
  • 20. Copyright © 2012 Russel Winder 20
  • 21. final n = 100000 final delta = 1.0 / n final startTime = System.nanoTime() def sum = 0.0 for (i in 1 .. n) { sum += 1 / (1 + ((i - 0.5) * delta) ** 2) } final pi = 4 * delta * sum final elapseTime = (System.nanoTime() - startTime) / 1e9 Output.out(getClass().name, pi, n, elapseTime) Copyright © 2012 Russel Winder 21
  • 22. final int n = 1000000000 final double delta = 1.0 / n final startTimeNanos = System.nanoTime() double sum = 0.0 for (int i = 1; i <= n; ++i) { final double x = (i - 0.5d) * delta sum += 1.0d / (1.0d + x * x) } final double pi = 4.0 * delta * sum final elapseTime = (System.nanoTime() - startTimeNanos) / 1e9 Output.out(getClass().name, pi, n, elapseTime) Copyright © 2012 Russel Winder 22
  • 23. import groovy.transform.CompileStatic @CompileStatic execute() { final int n = 1000000000 final double delta = 1.0 / n final startTimeNanos = System.nanoTime () double sum = 0.0 for (int i = 1; i <= n; ++i) { final double x = (i - 0.5d) * delta sum += 1.0d / (1.0d + x * x) } final double pi = 4.0 * delta * sum final elapseTime = (System.nanoTime() - startTimeNanos) / 1e9 Output.out(getClass().name, pi, n, elapseTime) } execute() Copyright © 2012 Russel Winder 23
  • 24. final int n = 10000000 final double delta = 1.0 / n final startTime = System.nanoTime() final double pi = 4.0 * delta * (1i .. n).sum {int i -> final double x = (i - 0.5d) * delta 1.0d / (1.0d + x * x) } final elapseTime = (System.nanoTime() - startTime) / 1e9 Output.out(getClass().name, pi, n, elapseTime) Copyright © 2012 Russel Winder 24
  • 25. import groovy.transform.CompileStatic @CompileStatic execute() { final int n = 10000000 final double delta = 1.0 / n final startTime = System.nanoTime() final double pi = 4.0 * delta * (double)((1i .. n).sum {int i -> final double x = (i - 0.5d) * delta 1.0d / (1.0d + x * x) }) final elapseTime = (System.nanoTime() - startTime) / 1e9 Output.out(getClass().name, pi, n, elapseTime) } execute() Copyright © 2012 Russel Winder 25
  • 26. import groovyx.gpars.ParallelEnhancer void execute(final numberOfTasks) { final n = 1000000000 final delta = 1.0 / n final startTimeNanos = System.nanoTime () final sliceSize = (int)(n / numberOfTasks) final items = 0 ..< numberOfTasks ParallelEnhancer.enhanceInstance(items) final pi = 4.0 * delta * items.collectParallel {taskId -> PartialSum.dynamicCompile(taskId, sliceSize, delta) }.sumParallel() final elapseTime = (System.nanoTime() - startTimeNanos) / 1e9 Output.out(getClass().name, pi, n, elapseTime, numberOfTasks) } execute 1 execute 2 execute 8 execute 32 Copyright © 2012 Russel Winder 26
  • 27. static double dynamicCompile(final int taskId, final int sliceSize, final double delta) { final int start = 1i + taskId * sliceSize final int end = (taskId + 1i) * sliceSize double sum = 0.0d for (int i = start; i <= end; ++i) { final double x = (i - 0.5d) * delta sum += 1.0d / (1.0d + x * x) } sum } Copyright © 2012 Russel Winder 27
  • 28. Conclusion Copyright © 2012 Russel Winder 28
  • 29. There is nothing that Java can do that Groovy cannot do better. Copyright © 2012 Russel Winder 29
  • 31. Given Groovy Who Needs Java? Prof Russel Winder http://www.russel.org.uk email: russel@winder.org.uk xmpp: russel@winder.org.uk twitter: @russel_winder Copyright © 2012 Russel Winder 31
  • 32. Challenge Copyright © 2012 Russel Winder 32
  • 33. Problem Groovy Java Develop faster Execute faster Can be done at all Copyright © 2012 Russel Winder 33
  • 34. Given Groovy Who Needs Java? Prof Russel Winder http://www.russel.org.uk email: russel@winder.org.uk xmpp: russel@winder.org.uk twitter: @russel_winder Copyright © 2012 Russel Winder 34