The document discusses Groovy, an open source dynamic language for the Java Virtual Machine. It highlights Groovy's object-oriented and functional features, static typing support, seamless interoperability with Java, and suitability for scripting and domain-specific languages. Examples demonstrate Groovy's concise syntax and optional keywords for brevity.
Presented at JAX London 2013
Groovy is not a newcomer to the arena of alternative languages for the JVM. With over 1.7 million downloads a year, it's clearly ahead of the pack. But what makes it a great choice for your projects?
- a flat learning curve for Java developers
- its seamless Java integration where you can mix & mash Groovy & Java together
- a malleable & concise syntax fit for Domain-Specific Languages
- an interesting take on type safety
- its rich ecosystem of projects: Grails, Gradle, GPars, Spock, Griffon, Geb...
Presented at JAX London 2013
Groovy is not a newcomer to the arena of alternative languages for the JVM. With over 1.7 million downloads a year, it's clearly ahead of the pack. But what makes it a great choice for your projects?
- a flat learning curve for Java developers
- its seamless Java integration where you can mix & mash Groovy & Java together
- a malleable & concise syntax fit for Domain-Specific Languages
- an interesting take on type safety
- its rich ecosystem of projects: Grails, Gradle, GPars, Spock, Griffon, Geb...
Paco van der Linden, werkzaam als Senior ADF Ontwikkelaar bij AMIS, heeft met Groovy een aantal interessante oplossingen ontwikkeld. De kennis en ervaring die hij daarbij met Groovy in combinatie met Java (en ADF) heeft opgedaan, heeft hij op maandag 26 november gedeeld in een kennissessie.
Apache Groovy is a powerful, optionally typed and dynamic language, with static-typing and static compilation capabilities, for the Java platform aimed at improving developer productivity thanks to a concise, familiar and easy to learn syntax. It integrates smoothly with any Java program, and immediately delivers to your application powerful features, including scripting capabilities, Domain-Specific Language authoring, runtime and compile-time meta-programming and functional programming.
In this presentation, we'll see how Groovy simplifies the life of Java Developers. Basically, this talk would be for beginners where I would introduce powerful Groovy concepts like - Groovy Collections, Closure, Traits etc.
Groovy is a great language with extremely powerful capabilities about compile time meta-programming. Do you know that provides more than 40 AST transformations out-of-the box just to make your life as a developer easier?
In this talk you will learn the most important transformations provided by Groovy. I'll use a lot of code examples to explain all the concepts.
Madrid gug - sacando partido a las transformaciones ast de groovyIván López Martín
Groovy es un gran lenguaje con capacidades muy potentes de metaprogramación en tiempo de compilación. ¿Sabías que hay más de 40 transformaciones AST disponibles para hacernos la vida más fácil como desarrolladores?
En esta charla aprenderás las transformaciones más importantes que proporciona Groovy a través de muchos ejemplos para explicar todos los conceptos.
Greach 2015 AST – Groovy Transformers: More than meets the eye!Iván López Martín
Slides for my Greach 2015 talk: http://greachconf.com/speakers/ivan-lopez-ast-groovy-transformers-more-than-meets-the-eye/
The source code is: https://github.com/lmivan/greach2015
Groovy is a great language with extremely powerful capabilities about compile time meta-programming. Do you know that provides more than 40 AST transformations out-of-the box just to make your life as a developer easier?
In this talk you will learn the most important transformations provided by Groovy. I’ll use a lot of code examples to explain all the concepts.
Slides from my GeeCON 2014 Prague talk:
"Groovy is a dynamic language that provides different types of metaprogramming techniques. In this talk we’ll mainly see runtime metaprogramming. I’ll explain Groovy Meta-Object-Protocol (MOP), the metaclass, how to intercept method calls, how to deal with method missing and property missing, the use of mixins, traits and categories. All of these topics will be explained with examples in order to understand them.
Also, I’ll talk a little bit about compile-time metaprogramming with AST Transformations. AST Transformations provide a wonderful way of manipulating code at compile time via modifications of the Abstract Syntax Tree. We’ll see a basic but powerful example of what we can do with AST transformations."
The code is available at: https://github.com/lmivan/geecon2014-prague-metaprograming-with-groovy
Groovy is a dynamic language that provides different types of metaprogramming techniques. In this talk we’ll mainly see runtime metaprogramming. You’ll understand the Groovy Meta-Object-Protocol (MOP), the metaclass, how to intercept method calls, how to deal with method missing and property missing, the use of mixins, traits and categories. All of these topics will be explained with examples in order to understand them. Also, you’ll see a little bit about compile-time metaprogramming with AST Transformations. AST Transformations provide a wonderful way of manipulating code at compile time via modifications of the Abstract Syntax Tree. You’ll see a basic but powerful example of what we can do with AST transformations.
Meetup di GDG Italia - Leonardo Pirro - Codemotion Rome 2018 Codemotion
I Google Developer Group (GDG) sono una community internazionale di appassionati delle tecnologie: sviluppatori, designer e startupper. Sono suddivisi per città, e GDG Italia è la famiglia che rappresenta tutti i gruppi presenti sul territorio locale. Mike Trizio e Carmelo Ventimiglia introdurranno i GDG, le loro attività e perchè è utile e divertente farne parte. Leonardo Pirro invece ci introdurrà Kotlin, un linguaggio di programmazione che ha avuto un crescente successo negli ultimi anni. Analizzeremo le caratteristiche principali del linguaggio e i suoi vantaggi/benefici rispetto a Java.
The new class OOP system is being implemented in Perl now. It's been several years in development by a team of people with deep familiarity with object-oriented programming in other langauges, and also deep experience with Perl.
Let's see what that means and see some examples.
Paco van der Linden, werkzaam als Senior ADF Ontwikkelaar bij AMIS, heeft met Groovy een aantal interessante oplossingen ontwikkeld. De kennis en ervaring die hij daarbij met Groovy in combinatie met Java (en ADF) heeft opgedaan, heeft hij op maandag 26 november gedeeld in een kennissessie.
Apache Groovy is a powerful, optionally typed and dynamic language, with static-typing and static compilation capabilities, for the Java platform aimed at improving developer productivity thanks to a concise, familiar and easy to learn syntax. It integrates smoothly with any Java program, and immediately delivers to your application powerful features, including scripting capabilities, Domain-Specific Language authoring, runtime and compile-time meta-programming and functional programming.
In this presentation, we'll see how Groovy simplifies the life of Java Developers. Basically, this talk would be for beginners where I would introduce powerful Groovy concepts like - Groovy Collections, Closure, Traits etc.
Groovy is a great language with extremely powerful capabilities about compile time meta-programming. Do you know that provides more than 40 AST transformations out-of-the box just to make your life as a developer easier?
In this talk you will learn the most important transformations provided by Groovy. I'll use a lot of code examples to explain all the concepts.
Madrid gug - sacando partido a las transformaciones ast de groovyIván López Martín
Groovy es un gran lenguaje con capacidades muy potentes de metaprogramación en tiempo de compilación. ¿Sabías que hay más de 40 transformaciones AST disponibles para hacernos la vida más fácil como desarrolladores?
En esta charla aprenderás las transformaciones más importantes que proporciona Groovy a través de muchos ejemplos para explicar todos los conceptos.
Greach 2015 AST – Groovy Transformers: More than meets the eye!Iván López Martín
Slides for my Greach 2015 talk: http://greachconf.com/speakers/ivan-lopez-ast-groovy-transformers-more-than-meets-the-eye/
The source code is: https://github.com/lmivan/greach2015
Groovy is a great language with extremely powerful capabilities about compile time meta-programming. Do you know that provides more than 40 AST transformations out-of-the box just to make your life as a developer easier?
In this talk you will learn the most important transformations provided by Groovy. I’ll use a lot of code examples to explain all the concepts.
Slides from my GeeCON 2014 Prague talk:
"Groovy is a dynamic language that provides different types of metaprogramming techniques. In this talk we’ll mainly see runtime metaprogramming. I’ll explain Groovy Meta-Object-Protocol (MOP), the metaclass, how to intercept method calls, how to deal with method missing and property missing, the use of mixins, traits and categories. All of these topics will be explained with examples in order to understand them.
Also, I’ll talk a little bit about compile-time metaprogramming with AST Transformations. AST Transformations provide a wonderful way of manipulating code at compile time via modifications of the Abstract Syntax Tree. We’ll see a basic but powerful example of what we can do with AST transformations."
The code is available at: https://github.com/lmivan/geecon2014-prague-metaprograming-with-groovy
Groovy is a dynamic language that provides different types of metaprogramming techniques. In this talk we’ll mainly see runtime metaprogramming. You’ll understand the Groovy Meta-Object-Protocol (MOP), the metaclass, how to intercept method calls, how to deal with method missing and property missing, the use of mixins, traits and categories. All of these topics will be explained with examples in order to understand them. Also, you’ll see a little bit about compile-time metaprogramming with AST Transformations. AST Transformations provide a wonderful way of manipulating code at compile time via modifications of the Abstract Syntax Tree. You’ll see a basic but powerful example of what we can do with AST transformations.
Meetup di GDG Italia - Leonardo Pirro - Codemotion Rome 2018 Codemotion
I Google Developer Group (GDG) sono una community internazionale di appassionati delle tecnologie: sviluppatori, designer e startupper. Sono suddivisi per città, e GDG Italia è la famiglia che rappresenta tutti i gruppi presenti sul territorio locale. Mike Trizio e Carmelo Ventimiglia introdurranno i GDG, le loro attività e perchè è utile e divertente farne parte. Leonardo Pirro invece ci introdurrà Kotlin, un linguaggio di programmazione che ha avuto un crescente successo negli ultimi anni. Analizzeremo le caratteristiche principali del linguaggio e i suoi vantaggi/benefici rispetto a Java.
The new class OOP system is being implemented in Perl now. It's been several years in development by a team of people with deep familiarity with object-oriented programming in other langauges, and also deep experience with Perl.
Let's see what that means and see some examples.
What's next for Reactive Systems ? Next is making apps communications reactive. This keynote presentation was given with Steve Gury from Facebook Engineering.
This is your one stop shop introduction to get oriented to the world of reactive programming. There are lots of such intros out there even manifestos. We hope this is the one where you don't get lost and it makes sense. Get a definition of what "reactive" means and why it matters. Learn about Reactive Streams and Reactive Extensions and the emerging ecosystem around them. Get a sense for what going reactive means for the programming model. See lots of hands-on demos introducing the basic concepts in composition libraries using RxJava and Reactor.
Essentials of Automations: Optimizing FME Workflows with ParametersSafe Software
Are you looking to streamline your workflows and boost your projects’ efficiency? Do you find yourself searching for ways to add flexibility and control over your FME workflows? If so, you’re in the right place.
Join us for an insightful dive into the world of FME parameters, a critical element in optimizing workflow efficiency. This webinar marks the beginning of our three-part “Essentials of Automation” series. This first webinar is designed to equip you with the knowledge and skills to utilize parameters effectively: enhancing the flexibility, maintainability, and user control of your FME projects.
Here’s what you’ll gain:
- Essentials of FME Parameters: Understand the pivotal role of parameters, including Reader/Writer, Transformer, User, and FME Flow categories. Discover how they are the key to unlocking automation and optimization within your workflows.
- Practical Applications in FME Form: Delve into key user parameter types including choice, connections, and file URLs. Allow users to control how a workflow runs, making your workflows more reusable. Learn to import values and deliver the best user experience for your workflows while enhancing accuracy.
- Optimization Strategies in FME Flow: Explore the creation and strategic deployment of parameters in FME Flow, including the use of deployment and geometry parameters, to maximize workflow efficiency.
- Pro Tips for Success: Gain insights on parameterizing connections and leveraging new features like Conditional Visibility for clarity and simplicity.
We’ll wrap up with a glimpse into future webinars, followed by a Q&A session to address your specific questions surrounding this topic.
Don’t miss this opportunity to elevate your FME expertise and drive your projects to new heights of efficiency.
JMeter webinar - integration with InfluxDB and GrafanaRTTS
Watch this recorded webinar about real-time monitoring of application performance. See how to integrate Apache JMeter, the open-source leader in performance testing, with InfluxDB, the open-source time-series database, and Grafana, the open-source analytics and visualization application.
In this webinar, we will review the benefits of leveraging InfluxDB and Grafana when executing load tests and demonstrate how these tools are used to visualize performance metrics.
Length: 30 minutes
Session Overview
-------------------------------------------
During this webinar, we will cover the following topics while demonstrating the integrations of JMeter, InfluxDB and Grafana:
- What out-of-the-box solutions are available for real-time monitoring JMeter tests?
- What are the benefits of integrating InfluxDB and Grafana into the load testing stack?
- Which features are provided by Grafana?
- Demonstration of InfluxDB and Grafana using a practice web application
To view the webinar recording, go to:
https://www.rttsweb.com/jmeter-integration-webinar
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...UiPathCommunity
💥 Speed, accuracy, and scaling – discover the superpowers of GenAI in action with UiPath Document Understanding and Communications Mining™:
See how to accelerate model training and optimize model performance with active learning
Learn about the latest enhancements to out-of-the-box document processing – with little to no training required
Get an exclusive demo of the new family of UiPath LLMs – GenAI models specialized for processing different types of documents and messages
This is a hands-on session specifically designed for automation developers and AI enthusiasts seeking to enhance their knowledge in leveraging the latest intelligent document processing capabilities offered by UiPath.
Speakers:
👨🏫 Andras Palfi, Senior Product Manager, UiPath
👩🏫 Lenka Dulovicova, Product Program Manager, UiPath
Accelerate your Kubernetes clusters with Varnish CachingThijs Feryn
A presentation about the usage and availability of Varnish on Kubernetes. This talk explores the capabilities of Varnish caching and shows how to use the Varnish Helm chart to deploy it to Kubernetes.
This presentation was delivered at K8SUG Singapore. See https://feryn.eu/presentations/accelerate-your-kubernetes-clusters-with-varnish-caching-k8sug-singapore-28-2024 for more details.
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...DanBrown980551
Do you want to learn how to model and simulate an electrical network from scratch in under an hour?
Then welcome to this PowSyBl workshop, hosted by Rte, the French Transmission System Operator (TSO)!
During the webinar, you will discover the PowSyBl ecosystem as well as handle and study an electrical network through an interactive Python notebook.
PowSyBl is an open source project hosted by LF Energy, which offers a comprehensive set of features for electrical grid modelling and simulation. Among other advanced features, PowSyBl provides:
- A fully editable and extendable library for grid component modelling;
- Visualization tools to display your network;
- Grid simulation tools, such as power flows, security analyses (with or without remedial actions) and sensitivity analyses;
The framework is mostly written in Java, with a Python binding so that Python developers can access PowSyBl functionalities as well.
What you will learn during the webinar:
- For beginners: discover PowSyBl's functionalities through a quick general presentation and the notebook, without needing any expert coding skills;
- For advanced developers: master the skills to efficiently apply PowSyBl functionalities to your real-world scenarios.
Key Trends Shaping the Future of Infrastructure.pdfCheryl Hung
Keynote at DIGIT West Expo, Glasgow on 29 May 2024.
Cheryl Hung, ochery.com
Sr Director, Infrastructure Ecosystem, Arm.
The key trends across hardware, cloud and open-source; exploring how these areas are likely to mature and develop over the short and long-term, and then considering how organisations can position themselves to adapt and thrive.
Connector Corner: Automate dynamic content and events by pushing a buttonDianaGray10
Here is something new! In our next Connector Corner webinar, we will demonstrate how you can use a single workflow to:
Create a campaign using Mailchimp with merge tags/fields
Send an interactive Slack channel message (using buttons)
Have the message received by managers and peers along with a test email for review
But there’s more:
In a second workflow supporting the same use case, you’ll see:
Your campaign sent to target colleagues for approval
If the “Approve” button is clicked, a Jira/Zendesk ticket is created for the marketing design team
But—if the “Reject” button is pushed, colleagues will be alerted via Slack message
Join us to learn more about this new, human-in-the-loop capability, brought to you by Integration Service connectors.
And...
Speakers:
Akshay Agnihotri, Product Manager
Charlie Greenberg, Host
DevOps and Testing slides at DASA ConnectKari Kakkonen
My and Rik Marselis slides at 30.5.2024 DASA Connect conference. We discuss about what is testing, then what is agile testing and finally what is Testing in DevOps. Finally we had lovely workshop with the participants trying to find out different ways to think about quality and testing in different parts of the DevOps infinity loop.
Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024Tobias Schneck
As AI technology is pushing into IT I was wondering myself, as an “infrastructure container kubernetes guy”, how get this fancy AI technology get managed from an infrastructure operational view? Is it possible to apply our lovely cloud native principals as well? What benefit’s both technologies could bring to each other?
Let me take this questions and provide you a short journey through existing deployment models and use cases for AI software. On practical examples, we discuss what cloud/on-premise strategy we may need for applying it to our own infrastructure to get it to work from an enterprise perspective. I want to give an overview about infrastructure requirements and technologies, what could be beneficial or limiting your AI use cases in an enterprise environment. An interactive Demo will give you some insides, what approaches I got already working for real.
Neuro-symbolic is not enough, we need neuro-*semantic*Frank van Harmelen
Neuro-symbolic (NeSy) AI is on the rise. However, simply machine learning on just any symbolic structure is not sufficient to really harvest the gains of NeSy. These will only be gained when the symbolic structures have an actual semantics. I give an operational definition of semantics as “predictable inference”.
All of this illustrated with link prediction over knowledge graphs, but the argument is general.
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Jeffrey Haguewood
Sidekick Solutions uses Bonterra Impact Management (fka Social Solutions Apricot) and automation solutions to integrate data for business workflows.
We believe integration and automation are essential to user experience and the promise of efficient work through technology. Automation is the critical ingredient to realizing that full vision. We develop integration products and services for Bonterra Case Management software to support the deployment of automations for a variety of use cases.
This video focuses on the notifications, alerts, and approval requests using Slack for Bonterra Impact Management. The solutions covered in this webinar can also be deployed for Microsoft Teams.
Interested in deploying notification automations for Bonterra Impact Management? Contact us at sales@sidekicksolutionsllc.com to discuss next steps.
UiPath Test Automation using UiPath Test Suite series, part 3DianaGray10
Welcome to UiPath Test Automation using UiPath Test Suite series part 3. In this session, we will cover desktop automation along with UI automation.
Topics covered:
UI automation Introduction,
UI automation Sample
Desktop automation flow
Pradeep Chinnala, Senior Consultant Automation Developer @WonderBotz and UiPath MVP
Deepak Rai, Automation Practice Lead, Boundaryless Group and UiPath MVP
14. Show users live
updates as they come
A « push » approach vs a
« pull » approach
Handle a big
volume of events
15. Show users live
updates as they come
A « push » approach vs a
« pull » approach
Handle a big
volume of events
React fast to
new events
16. Show users live
updates as they come
A « push » approach vs a
« pull » approach
Handle a big
volume of events
React fast to
new events
Use promises, events,
streams to react fast and
stream updates to users as
they are ready
17. Show users live
updates as they come
Avoid blocking
and state
A « push » approach vs a
« pull » approach
Handle a big
volume of events
React fast to
new events
Use promises, events,
streams to react fast and
stream updates to users as
they are ready
18. Show users live
updates as they come
Fail gracefully
Avoid blocking
and state
A « push » approach vs a
« pull » approach
Handle a big
volume of events
React fast to
new events
Use promises, events,
streams to react fast and
stream updates to users as
they are ready
45. Speaking of conciseness...
A full Spring app in the span of a tweet!
@RestController
class
App
{
@RequestMapping("/")
String
home()
{
"Hello
World!"
}
}
57. Scripts versus Classes
public
class
Main
{
public
static
void
main(String[]
args)
{
System.out.println("Hello");
}
}
vs
@glaforge — @smaldini / #DV13-rtweb
!26
58. Scripts versus Classes
public
class
Main
{
public
static
void
main(String[]
args)
{
System.out.println("Hello");
}
}
vs
println
"Hello"
@glaforge — @smaldini / #DV13-rtweb
!26
87. Optional...
class
Greeter
{
String
owner
!
!
!
!
Let’s reformat that mess
of whitespace!
!
!
!
!
!
String
greet(String
name)
{
"Hello
${name},
I
am
${owner}"
}
}
!
def
greeter
=
new
Greeter(owner:
"Guillaume")
!
!
println
greeter.greet("Marion")
@glaforge — @smaldini / #DV13-rtweb
!39
88. Optional...
class
Greeter
{
String
owner
!
String
greet(String
name)
{
"Hello
${name},
I
am
${owner}"
}
}
!
def
greeter
=
new
Greeter(owner:
"Guillaume")
!
println
greeter.greet("Marion")
@glaforge — @smaldini / #DV13-rtweb
!40
89. Optional...
public
class
Greeter
{
private
String
owner;
!
public
String
getOwner()
{
class
Greeter
{
return
owner;
String
owner
}
!
!
String
greet(String
name)
{
public
void
setOwner(String
owner)
{
"Hello
${name},
I
am
${owner}"
this.owner
=
owner;
}
}
}
!
!
public
String
greet(String
name)
{
def
greeter
=
new
Greeter(owner:
"Guillaume")
return
"Hello
"
+
name
+
",
I
am
"
+
owner;
!
}
println
greeter.greet("Marion")
}
!
Greeter
greeter
=
new
Greeter();
greeter.setOwner("Guillaume");
!
System.out.println(greeter.greet("Marion"));
@glaforge — @smaldini / #DV13-rtweb
!40
90. Optional...
class
Greeter
{
String
owner
!
String
greet(String
name)
{
"Hello
${name},
I
am
${owner}"
}
}
!
def
greeter
=
new
Greeter(owner:
"Guillaume")
!
println
greeter.greet("Marion")
@glaforge — @smaldini / #DV13-rtweb
!40
91. Native syntax constructs
//
closures
def
adder
=
{
a,
b
-‐>
a
+
b
}
!
//
lists
def
list
=
[1,
2,
3,
4,
5]
!
//
maps
def
map
=
[a:
1,
b:
2,
c:
3]
!
//
regular
expressions
def
regex
=
~/.*foo.*/
!
//
ranges
def
range
128..255
@glaforge — @smaldini / #DV13-rtweb
!41
92. Closures — the basics
• Functions as first-class citizen of the language
def
adder
=
{
a,
b
-‐>
a
+
b
}
!
assert
adder(1,
2)
==
3
assert
adder('a',
'b')
==
'ab'
@glaforge — @smaldini / #DV13-rtweb
!42
93. Closures — the basics
• Functions as first-class citizen of the language
Closure
parameters
def
adder
=
{
a,
b
-‐>
a
+
b
}
!
assert
adder(1,
2)
==
3
assert
adder('a',
'b')
==
'ab'
@glaforge — @smaldini / #DV13-rtweb
!42
94. Closures — the basics
• Functions as first-class citizen of the language
Assign a function
Closure
into a variable
parameters
def
adder
=
{
a,
b
-‐>
a
+
b
}
!
assert
adder(1,
2)
==
3
assert
adder('a',
'b')
==
'ab'
@glaforge — @smaldini / #DV13-rtweb
!42
95. Closures — the basics
• Functions as first-class citizen of the language
Assign a function
Closure
into a variable
parameters
def
adder
=
{
a,
b
-‐>
a
+
b
}
!
assert
adder(1,
2)
==
3
assert
adder('a',
'b')
==
'ab'
Short form of:
adder.call(‘a’, ‘b’)
@glaforge — @smaldini / #DV13-rtweb
!42
96. Closures — the basics
• Functions as first-class citizen of the language
Assign a function
Closure
into a variable
parameters
def
adder
=
{
a,
b
-‐>
a
+
b
}
!
assert
adder(1,
2)
==
3
assert
adder('a',
'b')
==
'ab'
Short form of:
adder.call(‘a’, ‘b’)
@glaforge — @smaldini / #DV13-rtweb
Genericity with
duck typing & operator
overloading
!42
97. Closures — explicit type
!
def
intAdder
=
{
int
a,
int
b
-‐>
a
+
b
}
@glaforge — @smaldini / #DV13-rtweb
!43
98. Closures — explicit type
Be explicit about
the types
!
def
intAdder
=
{
int
a,
int
b
-‐>
a
+
b
}
@glaforge — @smaldini / #DV13-rtweb
!43
103. Closures — variable arguments
Variable number of
arguments
def
sum
=
{
...
elements
-‐>
elements.sum()
}
!
assert
sum(1,
2)
==
3
assert
sum('a',
'b',
'c')
==
'abc'
@glaforge — @smaldini / #DV13-rtweb
!45
104. Closures — variable arguments
You can specify the
type: int...
Variable number of
arguments
def
sum
=
{
...
elements
-‐>
elements.sum()
}
!
assert
sum(1,
2)
==
3
assert
sum('a',
'b',
'c')
==
'abc'
@glaforge — @smaldini / #DV13-rtweb
!45
105. Closures — default values
def
mult
=
{
int
a,
int
b
=
10
-‐>
a
*
b
}
!
assert
mult(2,
3)
==
6
assert
mult(5)
==
50
@glaforge — @smaldini / #DV13-rtweb
!46
106. Closures — default values
Default value
def
mult
=
{
int
a,
int
b
=
10
-‐>
a
*
b
}
!
assert
mult(2,
3)
==
6
assert
mult(5)
==
50
@glaforge — @smaldini / #DV13-rtweb
!46
107. Closures — default values
Default value
def
mult
=
{
int
a,
int
b
=
10
-‐>
a
*
b
}
!
assert
mult(2,
3)
==
6
assert
mult(5)
==
50
@glaforge — @smaldini / #DV13-rtweb
Provided value
for b
!46
108. Closures — default values
Default value
def
mult
=
{
int
a,
int
b
=
10
-‐>
a
*
b
}
!
assert
mult(2,
3)
==
6
assert
mult(5)
==
50
Default value
used for b
@glaforge — @smaldini / #DV13-rtweb
Provided value
for b
!46
112. Closures — map / filter / reduce
@groovy.transform.Immutable
class
Person
{
String
name
int
age
}
@glaforge — @smaldini / #DV13-rtweb
!48
113. Closures — map / filter / reduce
@groovy.transform.Immutable
class
Person
{
String
name
int
age
}
@glaforge — @smaldini / #DV13-rtweb
!48
114. Closures — map / filter / reduce
@groovy.transform.Immutable
class
Person
{
String
name
int
age
}
def
persons
=
[
new
Person('Guillaume',
36),
new
Person('Marion',
5),
new
Person('Erine',
1)
]
@glaforge — @smaldini / #DV13-rtweb
!48
115. Closures — map / filter / reduce
@groovy.transform.Immutable
class
Person
{
String
name
int
age
}
def
persons
=
[
new
Person('Guillaume',
36),
new
Person('Marion',
5),
new
Person('Erine',
1)
]
@glaforge — @smaldini / #DV13-rtweb
!48
116. Closures — map / filter / reduce
@groovy.transform.Immutable
class
Person
{
String
name
int
age
}
def
persons
=
[
new
Person('Guillaume',
36),
new
Person('Marion',
5),
new
Person('Erine',
1)
]
def
names
=
persons.findAll
{
it.age
<
18
}
.collect
{
it.name.toUpperCase()
}
.sort()
.join(',
')
@glaforge — @smaldini / #DV13-rtweb
!48
117. Closures — map / filter / reduce
@groovy.transform.Immutable
class
Person
{
String
name
int
age
}
def
persons
=
[
new
Person('Guillaume',
36),
new
Person('Marion',
5),
new
Person('Erine',
1)
]
def
names
=
persons.findAll
{
it.age
<
18
}
.collect
{
it.name.toUpperCase()
}
.sort()
.join(',
')
@glaforge — @smaldini / #DV13-rtweb
!48
118. Closures — map / filter / reduce
@groovy.transform.Immutable
class
Person
{
String
name
int
age
}
def
persons
=
[
new
Person('Guillaume',
36),
new
Person('Marion',
5),
new
Person('Erine',
1)
]
def
names
=
persons.findAll
{
it.age
<
18
}
.collect
{
it.name.toUpperCase()
}
.sort()
.join(',
')
assert
names
==
"ERINE,
MARION"
@glaforge — @smaldini / #DV13-rtweb
!48
119. Closures — map / filter / reduce
@groovy.transform.Immutable
class
Person
{
String
name
int
age
}
def
persons
=
[
new
Person('Guillaume',
36),
new
Person('Marion',
5),
new
Person('Erine',
1)
]
find/findAll, inject, collect, flatten,
min/max, unique, reverse, collate,
groupBy, any/every, head/tail/last,
count/countBy, combinations/
permutations/subsequences/
transpose, withDefault/
withLazyDefault
def
names
=
persons.findAll
{
it.age
<
18
}
.collect
{
it.name.toUpperCase()
}
.sort()
.join(',
')
assert
names
==
"ERINE,
MARION"
@glaforge — @smaldini / #DV13-rtweb
!48
120. Closures — resource handling
new
File('bible.txt').withReader
{
r
-‐>
new
File('out.txt').withWriter
{
w
-‐>
r.eachLine
{
line
-‐>
if
(line.contains('Groovy'))
w
<<
line.toUpperCase()
}
}
}
@glaforge — @smaldini / #DV13-rtweb
!49
121. Closures — resource handling
Take care of properly opening /
closing resources
new
File('bible.txt').withReader
{
r
-‐>
new
File('out.txt').withWriter
{
w
-‐>
r.eachLine
{
line
-‐>
if
(line.contains('Groovy'))
w
<<
line.toUpperCase()
}
}
}
@glaforge — @smaldini / #DV13-rtweb
!49
123. Closures — custom control structures
Closure as last argument
void
unless(boolean
cond,
Closure
c)
{
if
(!cond)
c()
}
!
unless
(10
<
9)
{
println
"less"
}
@glaforge — @smaldini / #DV13-rtweb
!50
124. Closures — custom control structures
Closure as last argument
void
unless(boolean
cond,
Closure
c)
{
if
(!cond)
c()
}
!
unless
(10
<
9)
{
println
"less"
}
@glaforge — @smaldini / #DV13-rtweb
Equivalent to:
unless(10<9, {...})
!50
125. Closures — custom control structures
class
Reactor
{
void
on(Selector
s,
Closure
c)
{
…
}
}
…
reactor.on(
$(‘abc')
)
{
Event<String>
ev
-‐>
…
}
@glaforge — @smaldini / #DV13-rtweb
!51
126. Closures — builders leverage closures
import
groovy.json.*
!
def
json
=
new
JsonBuilder()
json.person
{
name
'Guillaume'
age
36
daughters
'Marion',
'Erine'
address
{
street
'1
Main
Street'
zip
75001
city
'Paris'
}
}
@glaforge — @smaldini / #DV13-rtweb
!52
127. Closures — builders leverage closures
import
groovy.json.*
!
def
json
=
new
JsonBuilder()
json.person
{
name
'Guillaume'
age
36
daughters
'Marion',
'Erine'
address
{
street
'1
Main
Street'
zip
75001
city
'Paris'
}
}
@glaforge — @smaldini / #DV13-rtweb
Hierarchical data
representation
!52
128. Closures — builders leverage closures
import
groovy.json.*
!
Hierarchical data
representation
def
json
=
new
JsonBuilder()
json.person
{
name
'Guillaume'
age
36
Closure blocks
daughters
'Marion',
'Erine'
delimiting the
address
{
structure
street
'1
Main
Street'
zip
75001
city
'Paris'
}
}
@glaforge — @smaldini / #DV13-rtweb
!52
129. Closures — builders leverage closures
import
groovy.json.*
{
"person":
{
Hierarchical data
def
json
=
new
JsonBuilder()
"name":
"Guillaume",
representation
"age":
36,
json.person
{
"daughters":
[
name
'Guillaume'
"Marion",
"Erine"
age
36
],
Closure blocks
daughters
'Marion',
'Erine'
"address":
{
delimiting the
"street":
"1
Main
Street",
address
{
"zip":
75001,
structure
street
'1
Main
Street'
"city":
"Paris"
}
zip
75001
}
city
'Paris'
}
!
}
}
@glaforge — @smaldini / #DV13-rtweb
!52
130. Closure — your own builders
GroovyEnvironment.create
{
environment
{
defaultDispatcher
=
"test"
!
dispatcher('test')
{
type
=
DispatcherType.SYNCHRONOUS
}
}
}
@glaforge — @smaldini / #DV13-rtweb
!53
131. Closure — your own builders
GroovyEnvironment.create
{
environment
{
defaultDispatcher
=
"test"
!
dispatcher('test')
{
type
=
DispatcherType.SYNCHRONOUS
}
}
}
@glaforge — @smaldini / #DV13-rtweb
!53
132. Closure — your own builders
GroovyEnvironment.create
{
environment
{
defaultDispatcher
=
"test"
!
dispatcher('test')
{
type
=
DispatcherType.SYNCHRONOUS
}
}
}
@glaforge — @smaldini / #DV13-rtweb
!53
133. Closure — your own builders
GroovyEnvironment.create
{
environment
{
defaultDispatcher
=
"test"
!
dispatcher('test')
{
type
=
DispatcherType.SYNCHRONOUS
}
}
}
@glaforge — @smaldini / #DV13-rtweb
!53
134. Closure — your own builders
GroovyEnvironment.create
{
environment
{
defaultDispatcher
=
"test"
!
dispatcher('test')
{
type
=
DispatcherType.SYNCHRONOUS
}
}
}
@glaforge — @smaldini / #DV13-rtweb
!53
135. Closure — your own builders
Implement a builder extending
BuilderSupport or FactoryBuilderSupport…
GroovyEnvironment.create
{
or roll your own!
environment
{
defaultDispatcher
=
"test"
!
dispatcher('test')
{
type
=
DispatcherType.SYNCHRONOUS
}
}
}
@glaforge — @smaldini / #DV13-rtweb
!53
136. Closure — your own builders
Implement a builder extending
BuilderSupport or FactoryBuilderSupport…
GroovyEnvironment.create
{
or roll your own!
environment
{
defaultDispatcher
=
"test"
abstract
class
BuilderSupport
{
abstract
void
setParent(Object
parent,
Object
child)
!
abstract
Object
createNode(Object
name)
dispatcher('test')
{
abstract
Object
createNode(Object
name,
Object
value)
abstract
Object
createNode(Object
name,
Map
attributes)
type
=
DispatcherType.SYNCHRONOUS
abstract
Object
createNode(Object
name,
Map
attributes,
Object
value)
}
}
}
}
@glaforge — @smaldini / #DV13-rtweb
!53
137. GPath expressions
• GPath expressions are like XPath
but for an object graph
import
groovy.json.*
!
def
url
=
"https://api.github.com/repos/groovy/groovy-‐core/commits"
!
def
commits
=
new
JsonSlurper().parseText(url.toURL().text)
!
assert
commits[0].commit.author.name
==
'Cedric
Champeau'
@glaforge — @smaldini / #DV13-rtweb
!54
138. GPath expressions
• GPath expressions are like XPath
but for an object graph
import
groovy.json.*
!
def
url
=
"https://api.github.com/repos/groovy/groovy-‐core/commits"
!
def
commits
=
new
JsonSlurper().parseText(url.toURL().text)
!
assert
commits[0].commit.author.name
==
'Cedric
Champeau'
GPath expression
@glaforge — @smaldini / #DV13-rtweb
!54
139. GPath expressions
• GPath expressions are like XPath
but for an object graph
import
groovy.json.*
!
def
url
=
"https://api.github.com/repos/groovy/groovy-‐core/commits"
!
def
commits
=
new
JsonSlurper().parseText(url.toURL().text)
!
assert
commits[0].commit.author.name
==
'Cedric
Champeau'
GPath expression
@glaforge — @smaldini / #DV13-rtweb
Add find / findAll
into the mix
!54
140. GPath expressions
• GPath expressions are like XPath
but for an object graph
No (un)marshalling!
import
groovy.json.*
!
def
url
=
"https://api.github.com/repos/groovy/groovy-‐core/commits"
!
def
commits
=
new
JsonSlurper().parseText(url.toURL().text)
!
assert
commits[0].commit.author.name
==
'Cedric
Champeau'
GPath expression
@glaforge — @smaldini / #DV13-rtweb
Add find / findAll
into the mix
!54
141. Lists
def
list
=
['a',
'b',
'c']
!
list
<<
'd'
assert
list.contains('d')
!
assert
list.findAll
{
it.startsWith
'a'
}.size()
==
1
assert
list.collect
{
it.toUpperCase()
}
==
['A',
'B',
'C',
'D']
assert
list.inject('')
{
a,
b
-‐>
a
+
b
}
==
'abcd'
@glaforge — @smaldini / #DV13-rtweb
!55
142. Lists
List definition
def
list
=
['a',
'b',
'c']
!
list
<<
'd'
assert
list.contains('d')
!
assert
list.findAll
{
it.startsWith
'a'
}.size()
==
1
assert
list.collect
{
it.toUpperCase()
}
==
['A',
'B',
'C',
'D']
assert
list.inject('')
{
a,
b
-‐>
a
+
b
}
==
'abcd'
@glaforge — @smaldini / #DV13-rtweb
!55
143. Lists
List definition
def
list
=
['a',
'b',
'c']
!
list
<<
'd'
assert
list.contains('d')
Append an element
(operator overloading)
!
assert
list.findAll
{
it.startsWith
'a'
}.size()
==
1
assert
list.collect
{
it.toUpperCase()
}
==
['A',
'B',
'C',
'D']
assert
list.inject('')
{
a,
b
-‐>
a
+
b
}
==
'abcd'
@glaforge — @smaldini / #DV13-rtweb
!55
144. Lists
List definition
def
list
=
['a',
'b',
'c']
!
list
<<
'd'
assert
list.contains('d')
Append an element
(operator overloading)
!
assert
list.findAll
{
it.startsWith
'a'
}.size()
==
1
assert
list.collect
{
it.toUpperCase()
}
==
['A',
'B',
'C',
'D']
assert
list.inject('')
{
a,
b
-‐>
a
+
b
}
==
'abcd'
Functional-style map /
filter / reduce with
closures
@glaforge — @smaldini / #DV13-rtweb
!55
169. BigDecimal by default!
assert
2.0
-‐
1.1
==
0.9
assert
3
/
2
==
1.5
One of the reasons why microbenchmarks sometimes showed
Groovy to be slow...
@glaforge — @smaldini / #DV13-rtweb
!62
170. BigDecimal by default!
assert
2.0
-‐
1.1
==
0.9
assert
3
/
2
==
1.5
One of the reasons why microbenchmarks sometimes showed
Groovy to be slow...
@glaforge — @smaldini / #DV13-rtweb
But you can use doubles & floats for
performance, with ‘d’ or ‘f ’ suffixes
or with explicit type
!62
173. Powerful switch /
case on steroids
switch(obj)
{
case
123:
"number
123";
break
case
"abc":
"string
abc";
break
case
String:
"is
a
string";
break
case
[1,
2,
3]:
"in
list";
break
case
~/.*o+.*/:
"regex
match";
break
case
{
it
<
3
}:
"closure
criteria";
break
default:
"unknown"
}
176. Named arguments
move
obj,
x:
3,
y:
4
Normal argument
@glaforge — @smaldini / #DV13-rtweb
Named argument
!64
177. Named arguments
move
obj,
x:
3,
y:
4
Normal argument
Named argument
Calls:
move(Map m, Object)
@glaforge — @smaldini / #DV13-rtweb
!64
178. Command chains
• Ability to chain method calls without parentheses and dots
move
forward
at
3.km/h
@glaforge — @smaldini / #DV13-rtweb
!65
179. Command chains
• Ability to chain method calls without parentheses and dots
move
forward
at
3.km/h
Actually equivalent to:
move(forward).at(3.getKm().div(h))
@glaforge — @smaldini / #DV13-rtweb
!65
180. Named arguments & command chains
check
that:
vodka
tastes
good
@glaforge — @smaldini / #DV13-rtweb
!66
181. Named arguments & command chains
check
that:
vodka
tastes
good
Will call:
check(that: vodka).tastes(good)
@glaforge — @smaldini / #DV13-rtweb
!66
182. Multiple assignment and destructuring
def
(a,
b)
=
['A',
'B']
!
(a,
b)
=
[b,
a]
!
def
(int
i,
int
j)
=
[1,
2]
!
def
geocode(String
place)
{
return
[45.4,
2.3]
}
!
def
(la,
lo)
=
geocode("Paris")
!
assert
la
==
45.4
&&
lo
==
2.3
@glaforge — @smaldini / #DV13-rtweb
!67
183. Multiple assignment and destructuring
def
(a,
b)
=
['A',
'B']
!
(a,
b)
=
[b,
a]
Classic « swap »
!
def
(int
i,
int
j)
=
[1,
2]
!
def
geocode(String
place)
{
return
[45.4,
2.3]
}
!
def
(la,
lo)
=
geocode("Paris")
!
assert
la
==
45.4
&&
lo
==
2.3
@glaforge — @smaldini / #DV13-rtweb
!67
184. Multiple assignment and destructuring
def
(a,
b)
=
['A',
'B']
!
With types
(a,
b)
=
[b,
a]
Classic « swap »
!
def
(int
i,
int
j)
=
[1,
2]
!
def
geocode(String
place)
{
return
[45.4,
2.3]
}
!
def
(la,
lo)
=
geocode("Paris")
!
assert
la
==
45.4
&&
lo
==
2.3
@glaforge — @smaldini / #DV13-rtweb
!67
185. Multiple assignment and destructuring
def
(a,
b)
=
['A',
'B']
!
With types
(a,
b)
=
[b,
a]
Classic « swap »
!
def
(int
i,
int
j)
=
[1,
2]
!
Method
returning a list
def
geocode(String
place)
{
return
[45.4,
2.3]
}
!
def
(la,
lo)
=
geocode("Paris")
!
assert
la
==
45.4
&&
lo
==
2.3
@glaforge — @smaldini / #DV13-rtweb
!67
186. Multiple assignment and destructuring
def
(a,
b)
=
['A',
'B']
!
With types
(a,
b)
=
[b,
a]
Classic « swap »
!
def
(int
i,
int
j)
=
[1,
2]
!
Method
returning a list
def
geocode(String
place)
{
return
[45.4,
2.3]
}
Destructuring
!
def
(la,
lo)
=
geocode("Paris")
!
assert
la
==
45.4
&&
lo
==
2.3
@glaforge — @smaldini / #DV13-rtweb
!67
187. Multiple assignment and destructuring
class
Point
{
double
x,
y
!
double
getAt(int
idx)
{
if
(idx
==
0)
x
else
if
(idx
==
1)
y
else
throw
new
Exception("Wrong
index")
}
}
!
def
(x,
y)
=
new
Point(x:
48.3,
y:
3.5)
!
assert
x
==
48.3
&&
y
==
3.5
@glaforge — @smaldini / #DV13-rtweb
!68
188. Multiple assignment and destructuring
class
Point
{
double
x,
y
Method signature
convention: getAt(int)
!
double
getAt(int
idx)
{
if
(idx
==
0)
x
else
if
(idx
==
1)
y
else
throw
new
Exception("Wrong
index")
}
}
!
def
(x,
y)
=
new
Point(x:
48.3,
y:
3.5)
!
assert
x
==
48.3
&&
y
==
3.5
@glaforge — @smaldini / #DV13-rtweb
!68
189. Multiple assignment and destructuring
class
Point
{
double
x,
y
Method signature
convention: getAt(int)
!
double
getAt(int
idx)
{
if
(idx
==
0)
x
else
if
(idx
==
1)
y
else
throw
new
Exception("Wrong
index")
}
}
Transparent destructuring
!
def
(x,
y)
=
new
Point(x:
48.3,
y:
3.5)
!
assert
x
==
48.3
&&
y
==
3.5
@glaforge — @smaldini / #DV13-rtweb
!68
190. Operator overloading
import
static
Unit.*
!
enum
Unit
{
M(1),
KM(1000)
!
double
mult
Unit(double
mult)
{
this.mult
=
mult
}
}
@glaforge — @smaldini / #DV13-rtweb
!69
191. Operator overloading
import
static
Unit.*
!
enum
Unit
{
M(1),
KM(1000)
!
import
groovy.transform.Immutable
import
static
Unit.*
double
mult
Unit(double
mult)
{
!
this.mult
=
mult
@Immutable
}
class
Distance
{
}
double
q
Unit
u
!
Distance
plus(Distance
d)
{
new
Distance(
q
*
u.mult
+
d.q
*
d.u.mult,
M)
}
}
@glaforge — @smaldini / #DV13-rtweb
!69
192. Operator overloading
import
static
Unit.*
!
import
static
Unit.*
enum
Unit
{
M(1),
KM(1000)
!
def
d10
=
new
Distance(10,
M)
!
import
groovy.transform.Immutable
def
d15
=
new
Distance(15,
M)
double
mult
import
static
Unit.*
!
Unit(double
mult)
{
!
def
d25
=
d10
+
d15
this.mult
=
mult
@Immutable
!
}
class
Distance
{
assert
d25.q
==
25
&&
d25.u
==
M
}
double
q
Unit
u
!
Distance
plus(Distance
d)
{
new
Distance(
q
*
u.mult
+
d.q
*
d.u.mult,
M)
}
}
@glaforge — @smaldini / #DV13-rtweb
!69
193. Operator overloading
import
static
Unit.*
!
import
static
Unit.*
enum
Unit
{
M(1),
KM(1000)
!
def
d10
=
new
Distance(10,
M)
!
import
groovy.transform.Immutable
def
d15
=
new
Distance(15,
M)
double
mult
import
static
Unit.*
!
Unit(double
mult)
{
!
def
d25
=
d10
+
d15
this.mult
=
mult
@Immutable
!
}
class
Distance
{
assert
d25.q
==
25
&&
d25.u
==
M
}
double
q
Unit
u
Overload the ‘+’
operator
@glaforge — @smaldini / #DV13-rtweb
!
Distance
plus(Distance
d)
{
new
Distance(
q
*
u.mult
+
d.q
*
d.u.mult,
M)
}
}
!69
194. Operator overloading
import
static
Unit.*
!
import
static
Unit.*
enum
Unit
{
M(1),
KM(1000)
!
def
d10
=
new
Distance(10,
M)
!
import
groovy.transform.Immutable
def
d15
=
new
Distance(15,
M)
double
mult
import
static
Unit.*
!
Unit(double
mult)
{
!
def
d25
=
d10
+
d15
this.mult
=
mult
@Immutable
!
}
class
Distance
{
assert
d25.q
==
25
&&
d25.u
==
M
}
double
q
Unit
u
Overload the ‘+’
operator
@glaforge — @smaldini / #DV13-rtweb
!
Distance
plus(Distance
d)
{
new
Distance(
q
*
u.mult
+
d.q
*
d.u.mult,
M)
}
}
Use ‘+’
!69
195. Operator overloading
a
+
b
//
a.plus(b)
a
-‐
b
//
a.minus(b)
a
*
b
//
a.multiply(b)
a
/
b
//
a.div(b)
a
%
b
//
a.modulo(b)
a
**
b
//
a.power(b)
a
|
b
//
a.or(b)
a
&
b
//
a.and(b)
a
^
b
//
a.xor(b)
a[b]
//
a.getAt(b)
a
<<
b
//
a.leftShift(b)
a
>>
b
//
a.rightShift(b)
a
>>>
b
//
a.rightShiftUnsigned(b)
+a
//
a.unaryPlus()
-‐a
//
a.unaryMinus()
~a
//
a.bitwiseNegate()
@glaforge — @smaldini / #DV13-rtweb
!70
196. Operator overloading
a
+
b
//
a.plus(b)
a
-‐
b
//
a.minus(b)
a
*
b
//
a.multiply(b)
Operator overloading is
a
/
b
//
a.div(b)
a
%
b
//
a.modulo(b)
just a convention on
a
**
b
//
a.power(b)
method names
a
|
b
//
a.or(b)
a
&
b
//
a.and(b)
a
^
b
//
a.xor(b)
a[b]
//
a.getAt(b)
a
<<
b
//
a.leftShift(b)
a
>>
b
//
a.rightShift(b)
a
>>>
b
//
a.rightShiftUnsigned(b)
+a
//
a.unaryPlus()
-‐a
//
a.unaryMinus()
~a
//
a.bitwiseNegate()
@glaforge — @smaldini / #DV13-rtweb
!70
197. Power asserts
def
(a,
b,
c)
=
[20,
30,
40]
!
assert
a
*
(b
-‐
1)
/
10
==
3
*
c
/
2
+
1
@glaforge — @smaldini / #DV13-rtweb
!71
199. Power asserts
def
(a,
b,
c)
=
[20,
30,
40]
!
assert
a
*
(b
-‐
1)
/
10
==
3
*
c
/
2
+
1
Assertion
failed:
!
assert
a
*
(b
-‐
1)
/
10
==
3
*
c
/
2
+
1
|
|
|
|
|
|
|
|
|
|
|
580|
29
58
false|
|
60
61
20
30
|
40
120
!
Invented by the Spock testing framework
at
script1.run(script1.groovy:3)
@glaforge — @smaldini / #DV13-rtweb
!71
200. Null handling
class
Order
{
LineItem
line
}
class
LineItem
{
int
quantity
Item
item
}
class
Item
{
String
name
}
!
def
o
=
new
Order(
line:
new
LineItem(
quantity:
2,
item:
null))
!
println
o.line.item.name
@glaforge — @smaldini / #DV13-rtweb
!72
201. Null handling
class
Order
{
LineItem
line
}
class
LineItem
{
int
quantity
Item
item
}
class
Item
{
String
name
}
!
def
o
=
new
Order(
line:
new
LineItem(
quantity:
2,
item:
null))
With Java, you only get an NPE.
No idea where it came from!
!
println
o.line.item.name
@glaforge — @smaldini / #DV13-rtweb
!72
202. Null handling
class
Order
{
LineItem
line
}
class
LineItem
{
int
quantity
Item
item
}
class
Item
{
String
name
}
!
def
o
=
new
Order(
line:
new
LineItem(
quantity:
2,
item:
null))
!
println
o.line.item.name
@glaforge — @smaldini / #DV13-rtweb
With Java, you only get an NPE.
No idea where it came from!
Groovy will say:
Cannot get property ‘name’ on null object
!72
203. Null handling
class
Order
{
LineItem
line
}
class
LineItem
{
int
quantity
Item
item
}
class
Item
{
String
name
}
!
def
o
=
new
Order(
line:
new
LineItem(
quantity:
2,
item:
null))
!
println
o.line.item.name
@glaforge — @smaldini / #DV13-rtweb
!72
204. Null handling
class
Order
{
LineItem
line
}
class
LineItem
{
int
quantity
Item
item
}
class
Item
{
String
name
}
o?.line?.item?.name
!
def
o
=
new
Order(
line:
new
LineItem(
quantity:
2,
item:
null))
!
println
o.line.item.name
@glaforge — @smaldini / #DV13-rtweb
!72
205. Null handling
class
Order
{
LineItem
line
}
class
LineItem
{
int
quantity
Item
item
}
class
Item
{
String
name
}
o?.line?.item?.name
Safe navigation:
will just return
null; No NPE
!
def
o
=
new
Order(
line:
new
LineItem(
quantity:
2,
item:
null))
!
println
o.line.item.name
@glaforge — @smaldini / #DV13-rtweb
!72
219. Towards Elvis...
def
(x,
y)
=
['MacBook
Pro',
'unknown']
if
(x
!=
null
&&
x.size()
>
0)
x
else
y
@glaforge — @smaldini / #DV13-rtweb
!77
220. Towards Elvis...
def
(x,
y)
=
['MacBook
Pro',
'unknown']
if
(x
!=
null
&&
x.size()
>
0)
x
else
y
if
(x
&&
x.size())
x
else
y
@glaforge — @smaldini / #DV13-rtweb
!77
221. Towards Elvis...
def
(x,
y)
=
['MacBook
Pro',
'unknown']
if
(x
!=
null
&&
x.size()
>
0)
x
else
y
if
(x
&&
x.size())
x
else
y
if
(x)
x
else
y
@glaforge — @smaldini / #DV13-rtweb
!77
222. Towards Elvis...
def
(x,
y)
=
['MacBook
Pro',
'unknown']
if
(x
!=
null
&&
x.size()
>
0)
x
else
y
if
(x
&&
x.size())
x
else
y
if
(x)
x
else
y
x
?
x
:
y
@glaforge — @smaldini / #DV13-rtweb
!77
223. Towards Elvis...
def
(x,
y)
=
['MacBook
Pro',
'unknown']
if
(x
!=
null
&&
x.size()
>
0)
x
else
y
if
(x
&&
x.size())
x
else
y
if
(x)
x
else
y
x
?
x
:
y
x
?:
y
@glaforge — @smaldini / #DV13-rtweb
!77
224. Towards Elvis...
def
(x,
y)
=
['MacBook
Pro',
'unknown']
if
(x
!=
null
&&
x.size()
>
0)
x
else
y
if
(x
&&
x.size())
x
else
y
if
(x)
x
else
y
x
?
x
:
y
x
?:
y
Null, empty, zerosized... false,
otherwise true!
@glaforge — @smaldini / #DV13-rtweb
!77
225. Towards Elvis...
def
(x,
y)
=
['MacBook
Pro',
'unknown']
if
(x
!=
null
&&
x.size()
>
0)
x
else
y
if
(x
&&
x.size())
x
else
y
if
(x)
x
else
y
x
?
x
:
y
x
?:
y
Good old ternary
operator
@glaforge — @smaldini / #DV13-rtweb
Null, empty, zerosized... false,
otherwise true!
!77
226. Towards Elvis...
def
(x,
y)
=
['MacBook
Pro',
'unknown']
if
(x
!=
null
&&
x.size()
>
0)
x
else
y
if
(x
&&
x.size())
x
else
y
if
(x)
x
else
y
x
?
x
:
y
x
?:
y
Elvis!
@glaforge — @smaldini / #DV13-rtweb
Good old ternary
operator
Null, empty, zerosized... false,
otherwise true!
!77
227. AST transformations
• Abstract Syntax Tree
– in memory representation of your program
before being compiled into bytecode
!
• AST transformation == process of transforming the AST of a
program before it’s compiled
!
• Macro-like compiler hook!
@glaforge — @smaldini / #DV13-rtweb
!78
231. Immutability
• Implement immutability
by the book
!
– final class
– tuple-style constructor
– private final backing fields
– defensive copying of collections
– equals() and hashCode() methods
– toString() method
– ...
@glaforge — @smaldini / #DV13-rtweb
!82
232. Immutability
• Implement immutability
by the book
!
Can be error-prone to
write immutable
classes oneself!
– final class
– tuple-style constructor
– private final backing fields
– defensive copying of collections
– equals() and hashCode() methods
– toString() method
– ...
@glaforge — @smaldini / #DV13-rtweb
!82
233. Immutability
• A Person class with
– a String name
– an int age
public final class Person {!
private final String name;!
private final int age;!
!
!
!
!
!
!
public Person(String name, int age) {!
this.name = name;!
this.age = age;!
}!
public String getName() {!
return name;!
}!
public int getAge() {!
return age;!
}!
public int hashCode() {!
return age + 31 * name.hashCode();!
}!
public boolean equals(Object other) {!
if (other == null) {!
return false;!
}!
if (this == other) {!
return true;!
}!
if (Person.class != other.getClass()) {!
return false;!
}!
Person otherPerson = (Person)other;!
if (!name.equals(otherPerson.getName()) {!
return false;!
}!
if (age != otherPerson.getAge()) {!
return false;!
}!
return true;!
}!
public String toString() {!
return "Person(" + name + ", " + age + ")";!
}!
}!
@glaforge — @smaldini / #DV13-rtweb
!83
234. Immutability
• A Person class with
– a String name
– an int age
public final class Person {!
private final String name;!
private final int age;!
!
!
!
!
!
!
public Person(String name, int age) {!
this.name = name;!
this.age = age;!
}!
Damn
verbose
Java!
public String getName() {!
return name;!
}!
public int getAge() {!
return age;!
}!
public int hashCode() {!
return age + 31 * name.hashCode();!
}!
public boolean equals(Object other) {!
if (other == null) {!
return false;!
}!
if (this == other) {!
return true;!
}!
if (Person.class != other.getClass()) {!
return false;!
}!
Person otherPerson = (Person)other;!
if (!name.equals(otherPerson.getName()) {!
return false;!
}!
if (age != otherPerson.getAge()) {!
return false;!
}!
return true;!
}!
public String toString() {!
return "Person(" + name + ", " + age + ")";!
}!
}!
@glaforge — @smaldini / #DV13-rtweb
!83
235. Immutability
• A Person class with
– a String name
– an int age
public final class Person {!
private final String name;!
private final int age;!
!
!
!
!
!
!
public Person(String name, int age) {!
this.name = name;!
this.age = age;!
}!
Damn
verbose
Java!
public String getName() {!
return name;!
}!
public int getAge() {!
return age;!
}!
public int hashCode() {!
return age + 31 * name.hashCode();!
}!
public boolean equals(Object other) {!
if (other == null) {!
return false;!
}!
if (this == other) {!
return true;!
}!
if (Person.class != other.getClass()) {!
return false;!
}!
Person otherPerson = (Person)other;!
if (!name.equals(otherPerson.getName()) {!
return false;!
}!
if (age != otherPerson.getAge()) {!
return false;!
}!
return true;!
}!
Although it’s also a
valid Groovy
program!
public String toString() {!
return "Person(" + name + ", " + age + ")";!
}!
}!
@glaforge — @smaldini / #DV13-rtweb
!83
237. Memoization
• Cache the result of previous invocations of closures or
methods with the same set of argument values
import
groovy.transform.*
!
@Memoized
long
fib(long
n)
{
if
(n
==
0)
0
else
if
(n
==
1)
1
else
fib(n
-‐
1)
+
fib(n
-‐
2)
}
!
println
fib(40)
@glaforge — @smaldini / #DV13-rtweb
!85
238. Memoization
• Cache the result of previous invocations of closures or
methods with the same set of argument values
import
groovy.transform.*
Best applied to
side-effect free
functions
!
@Memoized
long
fib(long
n)
{
if
(n
==
0)
0
else
if
(n
==
1)
1
else
fib(n
-‐
1)
+
fib(n
-‐
2)
}
!
println
fib(40)
@glaforge — @smaldini / #DV13-rtweb
!85
242. Groovy allows you
to be lazy
More concise, more
readable code
The compiler will do
the job for you
243. Groovy allows you
to be lazy
More concise, more
readable code
The compiler will do
the job for you
Less stuff to maintain
and worry about
244. @TypeChecked & @CompileStatic
• Static type checking with @TypeChecked, throws
compilation errors on...
– typos in method and variable names
– incompatible return types
– wrong type assignments
!
• Supports fine-grained type inference
– « Least Upper Bound »
– « Flow typing »
@glaforge — @smaldini / #DV13-rtweb
!87
245. @TypeChecked & @CompileStatic
• Static type checking with @TypeChecked, throws
compilation errors on...
– typos in method and variable names
– incompatible return types
– wrong type assignments
!
You can even extend the
static type checker!
• Supports fine-grained type inference
– « Least Upper Bound »
– « Flow typing »
@glaforge — @smaldini / #DV13-rtweb
!87
246. @TypeChecked & @CompileStatic
• Static type checking with @TypeChecked, throws
compilation errors on...
– typos in method and variable names
– incompatible return types
– wrong type assignments
!
You can even extend the
static type checker!
• Supports fine-grained type inference
– « Least Upper Bound »
– « Flow typing »
@glaforge — @smaldini / #DV13-rtweb
Type check DSLs or
dynamic features!
!87