SlideShare una empresa de Scribd logo
1 de 43
Descargar para leer sin conexión
What’s in Groovy for
Functional
Programming
Naresha K
@naresha_k
https://blog.nareshak.com/
APACHECON @HOME
Spt, 29th – Oct. 1st 2020
About me
Developer, Architect &
Tech Excellence Coach
Founder & Organiser
Bangalore Groovy User
Group
2
https://twitter.com/mfeathers/status/29581296216
3
4
String greet(String message) {
"Hello, ${message}"
}
String greet() {
"Hello"
}
String greet(String message, String friend) {
"Hello $friend, $message"
}
Regular Functions
5
String greet(String message) {
"Hello, ${message}"
}
def greet = { message -> "Hello, ${message}" }
// OR
def greet = { "Hello, ${it}" }
println greet("Good morning")
Closures are powerful
6
String greet() {
"Hello"
}
def greet = { -> "Hello" }
println greet()
7
String greet(String message, String friend) {
"Hello $friend, $message"
}
def greet = { message, friend -> "Hello $friend, $message" }
println greet()
8
def greet = { message -> "Hello, ${message}" }
def message = "Hello"
Integer age = 30
println greet("Good morning")
Closures are first class
9
@ToString(includePackage = false)
class Developer {
String name
int age
List<String> skills
}
List<Developer> developers = [
new Developer(name: 'Raj', age: 24, skills: ['Java',
'Groovy']),
new Developer(name: 'Sheldon', age: 30, skills: ['Java',
'Scala', 'Clojure']),
new Developer(name: 'Penny', age: 28, skills: ['Groovy',
'Scala']),
]
Sample data
10
List<Developer> findGroovyDevelopers(List<Developer> devs) {
List<Developer> groovyDevs = []
for(developer in devs) {
if(developer.skills.contains("Groovy")){
groovyDevs << developer
}
}
groovyDevs
}
println findGroovyDevelopers(developers)
Imperative code!
11
List<Developer> findGroovyDevelopers(List<Developer> devs) {
List<Developer> groovyDevs = []
for(developer in devs) {
if(developer.skills.contains("Groovy")){
groovyDevs << developer
}
}
groovyDevs
}
List<Developer> findGroovyDevelopers(List<Developer> devs) {
devs.findAll { dev -> dev.skills.contains('Groovy') }
}
Refactor to idiomatic Groovy
12
List<Developer> findGroovyDevelopers(List<Developer> devs) {
List<Developer> groovyDevs = []
for(developer in devs) {
if(developer.skills.contains("Groovy")){
groovyDevs << developer
}
}
groovyDevs
}
List<Developer> findGroovyDevelopers(List<Developer> devs) {
devs.findAll { dev -> dev.skills.contains('Groovy') }
}
Higher Order Function
13
List<Developer> findGroovyDevelopers(List<Developer> devs) {
devs.findAll { dev -> dev.skills.contains('Groovy') }
}
List<Developer> findGroovyDevelopers(List<Developer> devs) {
def knowsGroovy = { dev -> dev.skills.contains('Groovy') }
devs.findAll(knowsGroovy)
}
List<Developer> findDevelopers(List<Developer> devs,
Closure skillFinder) {
devs.findAll(skillFinder)
}
14
List<Developer> findDevelopers(List<Developer> devs, Closure
skillFinder) {
devs.findAll(skillFinder)
}
Closure createSkillFinder(String language) {
Closure skillFinder = { Developer developer ->
developer.skills.contains(language)
}
skillFinder
}
Closure knowsGroovy = createSkillFinder('Groovy')
println findDevelopers(developers, knowsGroovy)
15
Closure knowsGroovy = createSkillFinder('Groovy')
Closure knowsJava = createSkillFinder('Java')
println findDevelopers(developers, knowsGroovy)
println findDevelopers(developers, knowsJava)
16
Closure knowsGroovy = createSkillFinder('Groovy')
Closure knowsJava = createSkillFinder('Java')
println findDevelopers(developers, knowsGroovy)
println findDevelopers(developers, knowsJava)
Strategy Pattern
17
def command1 = {
println "Running command-1"
}
def command2 = {
println "Running command-2"
}
void runCommand(Closure command) {
command()
}
runCommand(command1)
runCommand(command2)
Command Pattern
18
def command1 = {
println "Running command-1"
}
def command2 = {
println "Running command-2"
}
void runCommand(Closure command) {
command()
}
[command1, command2].each { runCommand(it) }
Command Pattern
19
def command1 = {
println "Running command-1"
}
def command2 = {
println "Running command-2"
}
void runCommand(Closure command) {
println "Before command"
command()
println "After command"
}
[command1, command2].each { runCommand(it) }
Execute-Around Pattern
20
def add = { a, b -> a + b }
println add(10, 20)
21
def add = { a, b -> a + b }
println add(10, 20)
def increment = add.curry(1)
println increment(10)
Partial Application/ 

Currying
22
Closure createSkillFinder(String language) {
Closure skillFinder = { Developer developer ->
developer.skills.contains(language)
}
skillFinder
}
Closure knowsGroovy = createSkillFinder('Groovy')
Closure knowsJava = createSkillFinder('Java')
def findDevelopers = { List<Developer> devs, Closure skillFinder ->
devs.findAll(skillFinder)
}
23
def findDevelopers = { List<Developer> devs, Closure skillFinder ->
devs.findAll(skillFinder)
}
List<String> firstNamesOfDevs(List<Developer> devs, Closure
devSelector) {
List<Developer> selectedDevs = devSelector(devs)
selectedDevs.collect { it.name }
}
24
def findDevelopers = { List<Developer> devs, Closure skillFinder ->
devs.findAll(skillFinder)
}
List<String> firstNamesOfDevs(List<Developer> devs, Closure
devSelector) {
List<Developer> selectedDevs = devSelector(devs)
selectedDevs.collect { it.name }
}
def groovyDevSelector = findDevelopers.rcurry(knowsGroovy)
println firstNamesOfDevs(developers, groovyDevSelector)
25
println firstNamesOfDevs(developers, javaAndGroovyDevSelector)
26
Closure groovyDevSelector = findDevelopers.rcurry(knowsGroovy)
Closure javaDevSelector = findDevelopers.rcurry(knowsJava)
println firstNamesOfDevs(developers, javaAndGroovyDevSelector)
27
Closure groovyDevSelector = findDevelopers.rcurry(knowsGroovy)
Closure javaDevSelector = findDevelopers.rcurry(knowsJava)
Closure javaAndGroovyDevSelector =
groovyDevSelector << javaDevSelector
println firstNamesOfDevs(developers, javaAndGroovyDevSelector)
Function Composition
28
Closure knowsGroovy = { dev -> dev.skills.contains('Groovy') }
Closure ageOfDev = { Developer developer -> developer.age }
def averageAgeOfGroovyDevs = developers
.findAll(knowsGroovy)
.collect(ageOfDev)
.with { sum() / size() }
Map, filter, reduce
29
Closure knowsGroovy = { dev -> dev.skills.contains('Groovy') }
Closure ageOfDev = { Developer developer -> developer.age }
def averageAgeOfGroovyDevs = developers.stream()
.filter(knowsGroovy)
.map(ageOfDev)
.mapToInt(number -> number)
.average()
.orElse(0)
Streams API compatibility
30
Pure Functions
and
Immutable Data
31
// Instead of
developers.sort()
// Use
sortedData = developers.sort(false)
32
developers.asImmutable()
33
@Immutable
class Point {
int x
int y
}
new Point(x: 10, y: 20)
public final class Point { 

private final int x 

private final int y 

public Point(int x, int y) { // }

public Point(java.util.Map args) { // }

public Point() {

this ([:])

}

public final int getX() {

return x 

}

public final int getY() {

return y 

}

}
34
def numbers = [1, 2, 3, 4, 5]
println numbers.inject(0) { s, item -> s + item }
Iteration/ fold left
35
def numbers = [1, 2, 3, 4, 5]
def sum
sum = { head, tail ->
if (!tail) {
head
} else {
head + sum(tail.head(), tail.tail())
}
}
println(sum(0, numbers))
Recursion
36
import groovy.transform.*
@TailRecursive
def factorial(number, fact = 1) {
number == 0 ? fact : factorial(number - 1, fact * number)
}
println factorial(2500G)
Tail call optimisation
37
import groovy.transform.*
@TailRecursive
def factorial(number, fact = 1) {
number == 0 ? fact : factorial(number - 1, fact * number)
}
println factorial(2500G)
// factorial(3,1)
// factorial(2, 1 * 3)
// factorial(1, 1 * 3 * 2)
// factorial(0, 1 * 3 * 2 * 1)
// 1 * 3 * 2 * 1
// 6
38
import groovy.transform.Memoized
int timeConsumingOp(int number) {
Thread.sleep(5000)
number * number
}
println timeConsumingOp(10)
println timeConsumingOp(10)
println timeConsumingOp(10)
39
import groovy.transform.Memoized
@Memoized
int timeConsumingOp(int number) {
Thread.sleep(5000)
number * number
}
println timeConsumingOp(10)
println timeConsumingOp(10)
println timeConsumingOp(10)
Memoizing
40
https://blog.nareshak.com/whats-in-groovy-for-functional-programming/
41
Effective Java
With Groovy -
How Language
Influences Adoption of
Good Practices
APACHECON @HOME
Spt, 29th – Oct. 1st 2020
42
Thank You
APACHECON @HOME
Spt, 29th – Oct. 1st 2020
43

Más contenido relacionado

La actualidad más candente

All I know about rsc.io/c2go
All I know about rsc.io/c2goAll I know about rsc.io/c2go
All I know about rsc.io/c2goMoriyoshi Koizumi
 
プログラム実行の話と
OSとメモリの挙動の話
プログラム実行の話と
OSとメモリの挙動の話プログラム実行の話と
OSとメモリの挙動の話
プログラム実行の話と
OSとメモリの挙動の話tatsunori ishikawa
 
OSDC.TW - Gutscript for PHP haters
OSDC.TW - Gutscript for PHP hatersOSDC.TW - Gutscript for PHP haters
OSDC.TW - Gutscript for PHP hatersLin Yo-An
 
Dip Your Toes in the Sea of Security (PHP South Africa 2017)
Dip Your Toes in the Sea of Security (PHP South Africa 2017)Dip Your Toes in the Sea of Security (PHP South Africa 2017)
Dip Your Toes in the Sea of Security (PHP South Africa 2017)James Titcumb
 
Creating own language made easy
Creating own language made easyCreating own language made easy
Creating own language made easyIngvar Stepanyan
 
ClojurianからみたElixir
ClojurianからみたElixirClojurianからみたElixir
ClojurianからみたElixirKent Ohashi
 
Creating a compiler in Perl 6
Creating a compiler in Perl 6Creating a compiler in Perl 6
Creating a compiler in Perl 6Andrew Shitov
 
Melhorando sua API com DSLs
Melhorando sua API com DSLsMelhorando sua API com DSLs
Melhorando sua API com DSLsAugusto Pascutti
 
Climbing the Abstract Syntax Tree (PHP South Africa 2017)
Climbing the Abstract Syntax Tree (PHP South Africa 2017)Climbing the Abstract Syntax Tree (PHP South Africa 2017)
Climbing the Abstract Syntax Tree (PHP South Africa 2017)James Titcumb
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)James Titcumb
 
c++ project on restaurant billing
c++ project on restaurant billing c++ project on restaurant billing
c++ project on restaurant billing Swakriti Rathore
 
How To Think In Go
How To Think In GoHow To Think In Go
How To Think In Golestrrat
 
Hangman Game Programming in C (coding)
Hangman Game Programming in C (coding)Hangman Game Programming in C (coding)
Hangman Game Programming in C (coding)hasan0812
 
PHP in 2018 - Q4 - AFUP Limoges
PHP in 2018 - Q4 - AFUP LimogesPHP in 2018 - Q4 - AFUP Limoges
PHP in 2018 - Q4 - AFUP Limoges✅ William Pinaud
 
The Perl6 Type System
The Perl6 Type SystemThe Perl6 Type System
The Perl6 Type Systemabrummett
 
Learning Perl 6
Learning Perl 6 Learning Perl 6
Learning Perl 6 brian d foy
 

La actualidad más candente (20)

All I know about rsc.io/c2go
All I know about rsc.io/c2goAll I know about rsc.io/c2go
All I know about rsc.io/c2go
 
プログラム実行の話と
OSとメモリの挙動の話
プログラム実行の話と
OSとメモリの挙動の話プログラム実行の話と
OSとメモリの挙動の話
プログラム実行の話と
OSとメモリの挙動の話
 
Sbaw091006
Sbaw091006Sbaw091006
Sbaw091006
 
OSDC.TW - Gutscript for PHP haters
OSDC.TW - Gutscript for PHP hatersOSDC.TW - Gutscript for PHP haters
OSDC.TW - Gutscript for PHP haters
 
Dip Your Toes in the Sea of Security (PHP South Africa 2017)
Dip Your Toes in the Sea of Security (PHP South Africa 2017)Dip Your Toes in the Sea of Security (PHP South Africa 2017)
Dip Your Toes in the Sea of Security (PHP South Africa 2017)
 
ES2015 New Features
ES2015 New FeaturesES2015 New Features
ES2015 New Features
 
Creating own language made easy
Creating own language made easyCreating own language made easy
Creating own language made easy
 
ClojurianからみたElixir
ClojurianからみたElixirClojurianからみたElixir
ClojurianからみたElixir
 
Creating a compiler in Perl 6
Creating a compiler in Perl 6Creating a compiler in Perl 6
Creating a compiler in Perl 6
 
Melhorando sua API com DSLs
Melhorando sua API com DSLsMelhorando sua API com DSLs
Melhorando sua API com DSLs
 
Climbing the Abstract Syntax Tree (PHP South Africa 2017)
Climbing the Abstract Syntax Tree (PHP South Africa 2017)Climbing the Abstract Syntax Tree (PHP South Africa 2017)
Climbing the Abstract Syntax Tree (PHP South Africa 2017)
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
 
Tgh.pl
Tgh.plTgh.pl
Tgh.pl
 
c++ project on restaurant billing
c++ project on restaurant billing c++ project on restaurant billing
c++ project on restaurant billing
 
How To Think In Go
How To Think In GoHow To Think In Go
How To Think In Go
 
Hangman Game Programming in C (coding)
Hangman Game Programming in C (coding)Hangman Game Programming in C (coding)
Hangman Game Programming in C (coding)
 
PHP in 2018 - Q4 - AFUP Limoges
PHP in 2018 - Q4 - AFUP LimogesPHP in 2018 - Q4 - AFUP Limoges
PHP in 2018 - Q4 - AFUP Limoges
 
Beware sharp tools
Beware sharp toolsBeware sharp tools
Beware sharp tools
 
The Perl6 Type System
The Perl6 Type SystemThe Perl6 Type System
The Perl6 Type System
 
Learning Perl 6
Learning Perl 6 Learning Perl 6
Learning Perl 6
 

Similar a What's in Groovy for Functional Programming

Kotlin, smarter development for the jvm
Kotlin, smarter development for the jvmKotlin, smarter development for the jvm
Kotlin, smarter development for the jvmArnaud Giuliani
 
Lies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerLies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerGarth Gilmour
 
Lies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerLies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerGarth Gilmour
 
Groovy On Trading Desk (2010)
Groovy On Trading Desk (2010)Groovy On Trading Desk (2010)
Groovy On Trading Desk (2010)Jonathan Felch
 
.gradle 파일 정독해보기
.gradle 파일 정독해보기.gradle 파일 정독해보기
.gradle 파일 정독해보기경주 전
 
2007 09 10 Fzi Training Groovy Grails V Ws
2007 09 10 Fzi Training Groovy Grails V Ws2007 09 10 Fzi Training Groovy Grails V Ws
2007 09 10 Fzi Training Groovy Grails V Wsloffenauer
 
Introduction to kotlin + spring boot demo
Introduction to kotlin + spring boot demoIntroduction to kotlin + spring boot demo
Introduction to kotlin + spring boot demoMuhammad Abdullah
 
golang_getting_started.pptx
golang_getting_started.pptxgolang_getting_started.pptx
golang_getting_started.pptxGuy Komari
 
Kotlin / Android Update
Kotlin / Android UpdateKotlin / Android Update
Kotlin / Android UpdateGarth Gilmour
 
Kotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguaje
Kotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguajeKotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguaje
Kotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguajeVíctor Leonel Orozco López
 
Tuga IT 2018 Summer Edition - The Future of C#
Tuga IT 2018 Summer Edition - The Future of C#Tuga IT 2018 Summer Edition - The Future of C#
Tuga IT 2018 Summer Edition - The Future of C#Paulo Morgado
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
NetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf EditionNetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf EditionPaulo Morgado
 

Similar a What's in Groovy for Functional Programming (20)

Kotlin, smarter development for the jvm
Kotlin, smarter development for the jvmKotlin, smarter development for the jvm
Kotlin, smarter development for the jvm
 
Lies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerLies Told By The Kotlin Compiler
Lies Told By The Kotlin Compiler
 
Lies Told By The Kotlin Compiler
Lies Told By The Kotlin CompilerLies Told By The Kotlin Compiler
Lies Told By The Kotlin Compiler
 
Introduction to Groovy
Introduction to GroovyIntroduction to Groovy
Introduction to Groovy
 
Groovy On Trading Desk (2010)
Groovy On Trading Desk (2010)Groovy On Trading Desk (2010)
Groovy On Trading Desk (2010)
 
.gradle 파일 정독해보기
.gradle 파일 정독해보기.gradle 파일 정독해보기
.gradle 파일 정독해보기
 
Groovy!
Groovy!Groovy!
Groovy!
 
2007 09 10 Fzi Training Groovy Grails V Ws
2007 09 10 Fzi Training Groovy Grails V Ws2007 09 10 Fzi Training Groovy Grails V Ws
2007 09 10 Fzi Training Groovy Grails V Ws
 
Groovy
GroovyGroovy
Groovy
 
Why Kotlin is your next language?
Why Kotlin is your next language? Why Kotlin is your next language?
Why Kotlin is your next language?
 
Introduction to kotlin + spring boot demo
Introduction to kotlin + spring boot demoIntroduction to kotlin + spring boot demo
Introduction to kotlin + spring boot demo
 
golang_getting_started.pptx
golang_getting_started.pptxgolang_getting_started.pptx
golang_getting_started.pptx
 
Kotlin / Android Update
Kotlin / Android UpdateKotlin / Android Update
Kotlin / Android Update
 
Clojure And Swing
Clojure And SwingClojure And Swing
Clojure And Swing
 
Kotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguaje
Kotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguajeKotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguaje
Kotlin+MicroProfile: Enseñando trucos de 20 años a un nuevo lenguaje
 
Tuga IT 2018 Summer Edition - The Future of C#
Tuga IT 2018 Summer Edition - The Future of C#Tuga IT 2018 Summer Edition - The Future of C#
Tuga IT 2018 Summer Edition - The Future of C#
 
Clojure class
Clojure classClojure class
Clojure class
 
PHP and MySQL
PHP and MySQLPHP and MySQL
PHP and MySQL
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
NetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf EditionNetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf Edition
 

Más de Naresha K

The Groovy Way of Testing with Spock
The Groovy Way of Testing with SpockThe Groovy Way of Testing with Spock
The Groovy Way of Testing with SpockNaresha K
 
Evolving with Java - How to Remain Effective
Evolving with Java - How to Remain EffectiveEvolving with Java - How to Remain Effective
Evolving with Java - How to Remain EffectiveNaresha K
 
Take Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainersTake Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainersNaresha K
 
Implementing Resilience with Micronaut
Implementing Resilience with MicronautImplementing Resilience with Micronaut
Implementing Resilience with MicronautNaresha K
 
Take Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainersTake Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainersNaresha K
 
Favouring Composition - The Groovy Way
Favouring Composition - The Groovy WayFavouring Composition - The Groovy Way
Favouring Composition - The Groovy WayNaresha K
 
Effective Java with Groovy - How Language Influences Adoption of Good Practices
Effective Java with Groovy - How Language Influences Adoption of Good PracticesEffective Java with Groovy - How Language Influences Adoption of Good Practices
Effective Java with Groovy - How Language Influences Adoption of Good PracticesNaresha K
 
Effective Java with Groovy & Kotlin - How Languages Influence Adoption of Goo...
Effective Java with Groovy & Kotlin - How Languages Influence Adoption of Goo...Effective Java with Groovy & Kotlin - How Languages Influence Adoption of Goo...
Effective Java with Groovy & Kotlin - How Languages Influence Adoption of Goo...Naresha K
 
Effective Java with Groovy & Kotlin How Languages Influence Adoption of Good ...
Effective Java with Groovy & Kotlin How Languages Influence Adoption of Good ...Effective Java with Groovy & Kotlin How Languages Influence Adoption of Good ...
Effective Java with Groovy & Kotlin How Languages Influence Adoption of Good ...Naresha K
 
Eclipse Collections, Java Streams & Vavr - What's in them for Functional Pro...
Eclipse Collections, Java Streams & Vavr - What's in them for  Functional Pro...Eclipse Collections, Java Streams & Vavr - What's in them for  Functional Pro...
Eclipse Collections, Java Streams & Vavr - What's in them for Functional Pro...Naresha K
 
Implementing Cloud-Native Architectural Patterns with Micronaut
Implementing Cloud-Native Architectural Patterns with MicronautImplementing Cloud-Native Architectural Patterns with Micronaut
Implementing Cloud-Native Architectural Patterns with MicronautNaresha K
 
Groovy - Why and Where?
Groovy  - Why and Where?Groovy  - Why and Where?
Groovy - Why and Where?Naresha K
 
Leveraging Micronaut on AWS Lambda
Leveraging Micronaut on AWS LambdaLeveraging Micronaut on AWS Lambda
Leveraging Micronaut on AWS LambdaNaresha K
 
Groovy Refactoring Patterns
Groovy Refactoring PatternsGroovy Refactoring Patterns
Groovy Refactoring PatternsNaresha K
 
Implementing Cloud-native Architectural Patterns with Micronaut
Implementing Cloud-native Architectural Patterns with MicronautImplementing Cloud-native Architectural Patterns with Micronaut
Implementing Cloud-native Architectural Patterns with MicronautNaresha K
 
Effective Java with Groovy
Effective Java with GroovyEffective Java with Groovy
Effective Java with GroovyNaresha K
 
Evolving with Java - How to remain Relevant and Effective
Evolving with Java - How to remain Relevant and EffectiveEvolving with Java - How to remain Relevant and Effective
Evolving with Java - How to remain Relevant and EffectiveNaresha K
 
Effective Java with Groovy - How Language can Influence Good Practices
Effective Java with Groovy - How Language can Influence Good PracticesEffective Java with Groovy - How Language can Influence Good Practices
Effective Java with Groovy - How Language can Influence Good PracticesNaresha K
 
Beyond Lambdas & Streams - Functional Fluency in Java
Beyond Lambdas & Streams - Functional Fluency in JavaBeyond Lambdas & Streams - Functional Fluency in Java
Beyond Lambdas & Streams - Functional Fluency in JavaNaresha K
 
GORM - The polyglot data access toolkit
GORM - The polyglot data access toolkitGORM - The polyglot data access toolkit
GORM - The polyglot data access toolkitNaresha K
 

Más de Naresha K (20)

The Groovy Way of Testing with Spock
The Groovy Way of Testing with SpockThe Groovy Way of Testing with Spock
The Groovy Way of Testing with Spock
 
Evolving with Java - How to Remain Effective
Evolving with Java - How to Remain EffectiveEvolving with Java - How to Remain Effective
Evolving with Java - How to Remain Effective
 
Take Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainersTake Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainers
 
Implementing Resilience with Micronaut
Implementing Resilience with MicronautImplementing Resilience with Micronaut
Implementing Resilience with Micronaut
 
Take Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainersTake Control of your Integration Testing with TestContainers
Take Control of your Integration Testing with TestContainers
 
Favouring Composition - The Groovy Way
Favouring Composition - The Groovy WayFavouring Composition - The Groovy Way
Favouring Composition - The Groovy Way
 
Effective Java with Groovy - How Language Influences Adoption of Good Practices
Effective Java with Groovy - How Language Influences Adoption of Good PracticesEffective Java with Groovy - How Language Influences Adoption of Good Practices
Effective Java with Groovy - How Language Influences Adoption of Good Practices
 
Effective Java with Groovy & Kotlin - How Languages Influence Adoption of Goo...
Effective Java with Groovy & Kotlin - How Languages Influence Adoption of Goo...Effective Java with Groovy & Kotlin - How Languages Influence Adoption of Goo...
Effective Java with Groovy & Kotlin - How Languages Influence Adoption of Goo...
 
Effective Java with Groovy & Kotlin How Languages Influence Adoption of Good ...
Effective Java with Groovy & Kotlin How Languages Influence Adoption of Good ...Effective Java with Groovy & Kotlin How Languages Influence Adoption of Good ...
Effective Java with Groovy & Kotlin How Languages Influence Adoption of Good ...
 
Eclipse Collections, Java Streams & Vavr - What's in them for Functional Pro...
Eclipse Collections, Java Streams & Vavr - What's in them for  Functional Pro...Eclipse Collections, Java Streams & Vavr - What's in them for  Functional Pro...
Eclipse Collections, Java Streams & Vavr - What's in them for Functional Pro...
 
Implementing Cloud-Native Architectural Patterns with Micronaut
Implementing Cloud-Native Architectural Patterns with MicronautImplementing Cloud-Native Architectural Patterns with Micronaut
Implementing Cloud-Native Architectural Patterns with Micronaut
 
Groovy - Why and Where?
Groovy  - Why and Where?Groovy  - Why and Where?
Groovy - Why and Where?
 
Leveraging Micronaut on AWS Lambda
Leveraging Micronaut on AWS LambdaLeveraging Micronaut on AWS Lambda
Leveraging Micronaut on AWS Lambda
 
Groovy Refactoring Patterns
Groovy Refactoring PatternsGroovy Refactoring Patterns
Groovy Refactoring Patterns
 
Implementing Cloud-native Architectural Patterns with Micronaut
Implementing Cloud-native Architectural Patterns with MicronautImplementing Cloud-native Architectural Patterns with Micronaut
Implementing Cloud-native Architectural Patterns with Micronaut
 
Effective Java with Groovy
Effective Java with GroovyEffective Java with Groovy
Effective Java with Groovy
 
Evolving with Java - How to remain Relevant and Effective
Evolving with Java - How to remain Relevant and EffectiveEvolving with Java - How to remain Relevant and Effective
Evolving with Java - How to remain Relevant and Effective
 
Effective Java with Groovy - How Language can Influence Good Practices
Effective Java with Groovy - How Language can Influence Good PracticesEffective Java with Groovy - How Language can Influence Good Practices
Effective Java with Groovy - How Language can Influence Good Practices
 
Beyond Lambdas & Streams - Functional Fluency in Java
Beyond Lambdas & Streams - Functional Fluency in JavaBeyond Lambdas & Streams - Functional Fluency in Java
Beyond Lambdas & Streams - Functional Fluency in Java
 
GORM - The polyglot data access toolkit
GORM - The polyglot data access toolkitGORM - The polyglot data access toolkit
GORM - The polyglot data access toolkit
 

Último

SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odishasmiwainfosol
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringHironori Washizaki
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfStefano Stabellini
 
Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Rob Geurden
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfMarharyta Nedzelska
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfDrew Moseley
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalLionel Briand
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfFerryKemperman
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Mater
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024StefanoLambiase
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 

Último (20)

SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their Engineering
 
Xen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdfXen Safety Embedded OSS Summit April 2024 v4.pdf
Xen Safety Embedded OSS Summit April 2024 v4.pdf
 
Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...
 
A healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdfA healthy diet for your Java application Devoxx France.pdf
A healthy diet for your Java application Devoxx France.pdf
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdf
 
Precise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive GoalPrecise and Complete Requirements? An Elusive Goal
Precise and Complete Requirements? An Elusive Goal
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
Introduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdfIntroduction Computer Science - Software Design.pdf
Introduction Computer Science - Software Design.pdf
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
Dealing with Cultural Dispersion — Stefano Lambiase — ICSE-SEIS 2024
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 

What's in Groovy for Functional Programming

  • 1. What’s in Groovy for Functional Programming Naresha K @naresha_k https://blog.nareshak.com/ APACHECON @HOME Spt, 29th – Oct. 1st 2020
  • 2. About me Developer, Architect & Tech Excellence Coach Founder & Organiser Bangalore Groovy User Group 2
  • 4. 4
  • 5. String greet(String message) { "Hello, ${message}" } String greet() { "Hello" } String greet(String message, String friend) { "Hello $friend, $message" } Regular Functions 5
  • 6. String greet(String message) { "Hello, ${message}" } def greet = { message -> "Hello, ${message}" } // OR def greet = { "Hello, ${it}" } println greet("Good morning") Closures are powerful 6
  • 7. String greet() { "Hello" } def greet = { -> "Hello" } println greet() 7
  • 8. String greet(String message, String friend) { "Hello $friend, $message" } def greet = { message, friend -> "Hello $friend, $message" } println greet() 8
  • 9. def greet = { message -> "Hello, ${message}" } def message = "Hello" Integer age = 30 println greet("Good morning") Closures are first class 9
  • 10. @ToString(includePackage = false) class Developer { String name int age List<String> skills } List<Developer> developers = [ new Developer(name: 'Raj', age: 24, skills: ['Java', 'Groovy']), new Developer(name: 'Sheldon', age: 30, skills: ['Java', 'Scala', 'Clojure']), new Developer(name: 'Penny', age: 28, skills: ['Groovy', 'Scala']), ] Sample data 10
  • 11. List<Developer> findGroovyDevelopers(List<Developer> devs) { List<Developer> groovyDevs = [] for(developer in devs) { if(developer.skills.contains("Groovy")){ groovyDevs << developer } } groovyDevs } println findGroovyDevelopers(developers) Imperative code! 11
  • 12. List<Developer> findGroovyDevelopers(List<Developer> devs) { List<Developer> groovyDevs = [] for(developer in devs) { if(developer.skills.contains("Groovy")){ groovyDevs << developer } } groovyDevs } List<Developer> findGroovyDevelopers(List<Developer> devs) { devs.findAll { dev -> dev.skills.contains('Groovy') } } Refactor to idiomatic Groovy 12
  • 13. List<Developer> findGroovyDevelopers(List<Developer> devs) { List<Developer> groovyDevs = [] for(developer in devs) { if(developer.skills.contains("Groovy")){ groovyDevs << developer } } groovyDevs } List<Developer> findGroovyDevelopers(List<Developer> devs) { devs.findAll { dev -> dev.skills.contains('Groovy') } } Higher Order Function 13
  • 14. List<Developer> findGroovyDevelopers(List<Developer> devs) { devs.findAll { dev -> dev.skills.contains('Groovy') } } List<Developer> findGroovyDevelopers(List<Developer> devs) { def knowsGroovy = { dev -> dev.skills.contains('Groovy') } devs.findAll(knowsGroovy) } List<Developer> findDevelopers(List<Developer> devs, Closure skillFinder) { devs.findAll(skillFinder) } 14
  • 15. List<Developer> findDevelopers(List<Developer> devs, Closure skillFinder) { devs.findAll(skillFinder) } Closure createSkillFinder(String language) { Closure skillFinder = { Developer developer -> developer.skills.contains(language) } skillFinder } Closure knowsGroovy = createSkillFinder('Groovy') println findDevelopers(developers, knowsGroovy) 15
  • 16. Closure knowsGroovy = createSkillFinder('Groovy') Closure knowsJava = createSkillFinder('Java') println findDevelopers(developers, knowsGroovy) println findDevelopers(developers, knowsJava) 16
  • 17. Closure knowsGroovy = createSkillFinder('Groovy') Closure knowsJava = createSkillFinder('Java') println findDevelopers(developers, knowsGroovy) println findDevelopers(developers, knowsJava) Strategy Pattern 17
  • 18. def command1 = { println "Running command-1" } def command2 = { println "Running command-2" } void runCommand(Closure command) { command() } runCommand(command1) runCommand(command2) Command Pattern 18
  • 19. def command1 = { println "Running command-1" } def command2 = { println "Running command-2" } void runCommand(Closure command) { command() } [command1, command2].each { runCommand(it) } Command Pattern 19
  • 20. def command1 = { println "Running command-1" } def command2 = { println "Running command-2" } void runCommand(Closure command) { println "Before command" command() println "After command" } [command1, command2].each { runCommand(it) } Execute-Around Pattern 20
  • 21. def add = { a, b -> a + b } println add(10, 20) 21
  • 22. def add = { a, b -> a + b } println add(10, 20) def increment = add.curry(1) println increment(10) Partial Application/ Currying 22
  • 23. Closure createSkillFinder(String language) { Closure skillFinder = { Developer developer -> developer.skills.contains(language) } skillFinder } Closure knowsGroovy = createSkillFinder('Groovy') Closure knowsJava = createSkillFinder('Java') def findDevelopers = { List<Developer> devs, Closure skillFinder -> devs.findAll(skillFinder) } 23
  • 24. def findDevelopers = { List<Developer> devs, Closure skillFinder -> devs.findAll(skillFinder) } List<String> firstNamesOfDevs(List<Developer> devs, Closure devSelector) { List<Developer> selectedDevs = devSelector(devs) selectedDevs.collect { it.name } } 24
  • 25. def findDevelopers = { List<Developer> devs, Closure skillFinder -> devs.findAll(skillFinder) } List<String> firstNamesOfDevs(List<Developer> devs, Closure devSelector) { List<Developer> selectedDevs = devSelector(devs) selectedDevs.collect { it.name } } def groovyDevSelector = findDevelopers.rcurry(knowsGroovy) println firstNamesOfDevs(developers, groovyDevSelector) 25
  • 27. Closure groovyDevSelector = findDevelopers.rcurry(knowsGroovy) Closure javaDevSelector = findDevelopers.rcurry(knowsJava) println firstNamesOfDevs(developers, javaAndGroovyDevSelector) 27
  • 28. Closure groovyDevSelector = findDevelopers.rcurry(knowsGroovy) Closure javaDevSelector = findDevelopers.rcurry(knowsJava) Closure javaAndGroovyDevSelector = groovyDevSelector << javaDevSelector println firstNamesOfDevs(developers, javaAndGroovyDevSelector) Function Composition 28
  • 29. Closure knowsGroovy = { dev -> dev.skills.contains('Groovy') } Closure ageOfDev = { Developer developer -> developer.age } def averageAgeOfGroovyDevs = developers .findAll(knowsGroovy) .collect(ageOfDev) .with { sum() / size() } Map, filter, reduce 29
  • 30. Closure knowsGroovy = { dev -> dev.skills.contains('Groovy') } Closure ageOfDev = { Developer developer -> developer.age } def averageAgeOfGroovyDevs = developers.stream() .filter(knowsGroovy) .map(ageOfDev) .mapToInt(number -> number) .average() .orElse(0) Streams API compatibility 30
  • 32. // Instead of developers.sort() // Use sortedData = developers.sort(false) 32
  • 34. @Immutable class Point { int x int y } new Point(x: 10, y: 20) public final class Point { private final int x private final int y public Point(int x, int y) { // } public Point(java.util.Map args) { // } public Point() { this ([:]) } public final int getX() { return x } public final int getY() { return y } } 34
  • 35. def numbers = [1, 2, 3, 4, 5] println numbers.inject(0) { s, item -> s + item } Iteration/ fold left 35
  • 36. def numbers = [1, 2, 3, 4, 5] def sum sum = { head, tail -> if (!tail) { head } else { head + sum(tail.head(), tail.tail()) } } println(sum(0, numbers)) Recursion 36
  • 37. import groovy.transform.* @TailRecursive def factorial(number, fact = 1) { number == 0 ? fact : factorial(number - 1, fact * number) } println factorial(2500G) Tail call optimisation 37
  • 38. import groovy.transform.* @TailRecursive def factorial(number, fact = 1) { number == 0 ? fact : factorial(number - 1, fact * number) } println factorial(2500G) // factorial(3,1) // factorial(2, 1 * 3) // factorial(1, 1 * 3 * 2) // factorial(0, 1 * 3 * 2 * 1) // 1 * 3 * 2 * 1 // 6 38
  • 39. import groovy.transform.Memoized int timeConsumingOp(int number) { Thread.sleep(5000) number * number } println timeConsumingOp(10) println timeConsumingOp(10) println timeConsumingOp(10) 39
  • 40. import groovy.transform.Memoized @Memoized int timeConsumingOp(int number) { Thread.sleep(5000) number * number } println timeConsumingOp(10) println timeConsumingOp(10) println timeConsumingOp(10) Memoizing 40
  • 42. Effective Java With Groovy - How Language Influences Adoption of Good Practices APACHECON @HOME Spt, 29th – Oct. 1st 2020 42
  • 43. Thank You APACHECON @HOME Spt, 29th – Oct. 1st 2020 43