Discovering functional treasure in idiomatic Groovy
-
Upload
naresha-k -
Category
Technology
-
view
196 -
download
1
description
Transcript of Discovering functional treasure in idiomatic Groovy
![Page 1: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/1.jpg)
Discovering Functional Treasure in
Idiomatic Groovy
Naresha K Enteleki Solutions
@naresha_k
![Page 2: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/2.jpg)
![Page 3: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/3.jpg)
An imperative
language on JVM
A dynamic
with Functional Flavour
![Page 4: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/4.jpg)
The origin
http://radio-weblogs.com/0112098/2003/08/29.html
initial idea was to make a little dynamic language which compiles directly to Java classes and provides all the nice
(alleged) productivity benefits
- James Strachan
![Page 5: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/5.jpg)
Prerequisites
![Page 6: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/6.jpg)
Function
!def sayHello(){!! println 'Hello'!}!!sayHello()!
![Page 7: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/7.jpg)
![Page 8: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/8.jpg)
Closuredef wish = {!! println "Hello"!}!!wish()
def wishFriend = {!! println "Hello $it"!} !!wishFriend 'Raj'
def wishFriend = { to ->!! println "Hello $to"!}!!wishFriend 'Raj'
![Page 9: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/9.jpg)
Closure - No Arg
def wish = { ->!! println "Hello"!}!!wish()
![Page 10: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/10.jpg)
Closure - Multiple args
def wishWithMessage = { to, message ->!! println "Hello $to, $message"!}!!wishWithMessage "Raj", "Good Evening"
![Page 11: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/11.jpg)
Closures = Power functions
def wishWithMessage = { to, message ->!! println "Hello $to, $message"!}!!wishWithMessage "Raj", "Good Evening"
def <var> = <closure>
Functions as Values
![Page 12: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/12.jpg)
Sample Dataimport groovy.transform.ToString!!@ToString(includeNames=true)!class Geek{! String name! int age! List<String> languages!}
def geeks = []!geeks << new Geek(name: 'Raj', age: 24, !! languages: ['Java', 'Groovy'])!geeks << new Geek(name: 'Arun', age: 35, !! languages: ['Java', 'Scala', 'Clojure'])!geeks << new Geek(name: 'Kumar', age: 28, !! languages: ['Groovy', 'Scala'])!
![Page 13: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/13.jpg)
Geeks who can speak Groovy
def findGroovyGeeksImperative(geeks){!! def groovyGeeks = []!! for(geek in geeks){!! if(geek.languages.contains('Groovy')){!! groovyGeeks << geek!! }!! }!! groovyGeeks!}
![Page 14: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/14.jpg)
Geeks who can speak Groovy
def findGroovyGeeksImperative(geeks){!! def groovyGeeks = []!! for(geek in geeks){!
! if(geek.languages.contains('Groovy')){!
! groovyGeeks << geek!! }!! }!! groovyGeeks!}
![Page 15: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/15.jpg)
Generalised
def findGeeks(geeks, String language){!! def knowsLang = []!! for(geek in geeks){!! if(geek.languages.contains(language)){!! knowsLang << geek!! }!! }!! knowsLang!}!
![Page 16: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/16.jpg)
Towards Idiomatic Groovydef findGroovyGeeksFunctional(geeks){!! geeks.findAll({it.languages.contains('Groovy')})!}
def findGroovyGeeksFunctional(geeks){!! geeks.findAll() {it.languages.contains('Groovy')}!}
def findGroovyGeeksFunctional(geeks){!! geeks.findAll {it.languages.contains('Groovy')}!}
![Page 17: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/17.jpg)
Reusable
def knowsGroovy = { geek -> !! geek.languages.contains('Groovy')!}!!def findGeeksFunctional(geeks, criterion){!! geeks.findAll(criterion)!}!!println findGeeksFunctional(geeks, knowsGroovy)
Higher Order Functions
![Page 18: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/18.jpg)
Strategy Pattern
def knowsGroovy = { geek -> !! geek.languages.contains('Groovy')!}!!def knowsClojure = { geek ->!! geek.languages.contains('Clojure')!}!!def findGeeksFunctional(geeks, criterion){!! geeks.findAll(criterion)!}!!println findGeeksFunctional(geeks, knowsGroovy)!println findGeeksFunctional(geeks, knowsClojure)
![Page 19: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/19.jpg)
Command Pattern
def sayHello = {!! println "Hello"!}!!def sayHi = {!! println "Hi"!}!![sayHello, sayHi].each{ command ->!! command()!}
![Page 20: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/20.jpg)
Execute Arounddef sayHello = {!! println "Hello"!}!!def sayHi = {!! println "Hi"!}!![sayHello, sayHi].each{ command ->!! println "Before Command"!! command()!! println "After Command"!}
![Page 21: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/21.jpg)
Code Smell!
def knowsGroovy = { geek -> !! geek.languages.contains('Groovy')!}!!def knowsClojure = { geek ->!! geek.languages.contains('Clojure')!}
![Page 22: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/22.jpg)
After DRYing
def knowsLanguage = { geek, language ->!! geek.languages.contains(language)!}!!def findGeeks(geeks, criterion, String language){!! geeks.findAll {criterion(it, language)}!}!!println findGeeks(geeks, knowsLanguage, 'Groovy')
![Page 23: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/23.jpg)
A Better Approachdef knowsLanguage = { geek, language ->!! geek.languages.contains(language)!}!!def knowsGroovy = knowsLanguage.rcurry('Groovy')!def knowsClojure = knowsLanguage.rcurry('Clojure')!!def findGeeks(geeks, criterion){!! geeks.findAll(criterion)!}!!println findGeeks(geeks, knowsGroovy)!println findGeeks(geeks, knowsClojure)
Curried Functions
![Page 24: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/24.jpg)
Geeks
• Knows Groovy
• At least 25 years old
![Page 25: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/25.jpg)
Composing emdef atleast25YearsOld = { geek ->!! geek.age >= 25!}!!def findGeeks(geeks, criterion){!! geeks.findAll(criterion)!}!!def findGroovyGeeks = (this.&findGeeks)!! .rcurry(knowsGroovy)!def findGeeksAtLeast25 = (this.&findGeeks)!! .rcurry(atleast25YearsOld)
def findGroovyGeeksOlderThan24 = !! findGeeksAtLeast25 << findGroovyGeeks!!println findGroovyGeeksOlderThan24(geeks)
Function Composition
![Page 26: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/26.jpg)
Towards Immutable Datadef geeks = []!geeks << new Geek(name: 'Raj', age: 24, !! languages: ['Java', 'Groovy'])!geeks << new Geek(name: 'Arun', age: 35, !! languages: ['Java', 'Scala', 'Clojure'])!geeks << new Geek(name: 'Kumar', age: 28, !! languages: ['Groovy', 'Scala'])
geeks2 = geeks + new Geek(name: 'Mark', age: 40, !! languages: ['Lisp', 'Haskell'])
geeksImmutable = geeks.asImmutable()
![Page 27: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/27.jpg)
Towards Immutable Data …def geeksOrderedByAge = geeks.sort { it.age }!println geeksOrderedByAge!println geeks
def geeksOrderedByAge = geeks.sort false, { it.age }!println geeksOrderedByAge!println geeks
Pure Functions
![Page 28: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/28.jpg)
Demo
![Page 29: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/29.jpg)
import groovy.transform.*!!@TailRecursive!def factorial(number, fact = 1){!! number == 0 ? fact : factorial(number - 1, fact * number)!}!!println factorial(2500G)
Tail Call Optimization
![Page 30: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/30.jpg)
Prior to Groovy 2.3
def fact!fact = { number, result ->!! number == 0 ? result : !! ! fact.trampoline(number-1, result * number)!}.trampoline()
![Page 31: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/31.jpg)
Slow Functions
![Page 32: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/32.jpg)
import groovy.transform.*!!@Memoized!def timeConsumingOperation(int number){!! println "Performing computation"!! number * number!}!!println timeConsumingOperation(2)!println timeConsumingOperation(2)
Memoization
![Page 33: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/33.jpg)
Map Filter Reduce
println geeks.findAll { it.languages.contains('Groovy')}!! ! ! .collect {it.age}!! ! ! .sum()!!println geeks.findAll { it.languages.contains('Groovy')}!! ! ! .collect {it.age}!! ! ! .with{ sum()/ size()}
![Page 34: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/34.jpg)
Defer
![Page 35: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/35.jpg)
Deferimport groovy.transform.*!!class Website{!! String address!! @Lazy !! URL url = address.toURL()!}!!!def fuconf = new Website(address: 'http://functionalconf.com/')!println fuconf.dump()!!def content = fuconf.url.text!println content.grep("\n").size()!println fuconf.dump()!
Lazy Evaluation
![Page 36: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/36.jpg)
Recursion vs Iteration
![Page 37: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/37.jpg)
Recursion vs Iteration
def ages = geeks.collect { it.age }!!def sum!sum = { head, tail ->!! if(!tail){!! ! head!! }!! else{!! ! head + sum(tail.head(), tail.tail())!! }!}!!println(sum(0, ages))
![Page 38: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/38.jpg)
Recursion vs Iteration
println ages.inject(0) { s, item ->!! s + item!}
![Page 39: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/39.jpg)
The Ultimate Lesson
https://twitter.com/mfeathers/status/29581296216
![Page 40: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/40.jpg)
Functional Treasures Functions as values (First class citizens)
Higher order functions
Curried Functions
Function Composition
Pure Functions (Immutability)
Tail Call Optimization
Memoization
Lazy Evaluation
![Page 41: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/41.jpg)
Welcome to
![Page 42: Discovering functional treasure in idiomatic Groovy](https://reader031.fdocuments.us/reader031/viewer/2022020217/549c6492b47959a5318b473e/html5/thumbnails/42.jpg)
References
• https://github.com/naresha/functionalconf2014