SlideShare a Scribd company logo
:clojure/south - São Paulo, 2019
From Java to parallel Clojure
Leonardo Borges

@leonardo_borges

www.leonardoborges.com

www.recordpoint.com
A bit about me
• Head of Engineering at RecordPoint

• Founder of the Sydney Clojure User Group

• Open-source contributor 

• Author of bouncer and imminent

• Author of Clojure Reactive Programming
A bit about me
• 2nd edition is out now!
What about you?
What we’ll talk about
• Being a Lisp on the JVM

• Functional Programming strengths

• Concurrency and parallelism
Java has come a long way…
• ForkJoin;

• Lambda Expressions;

• Method References;

• CompletableFutures;

• JShell;

• Reactive Streams / Stream API;

• …and more!
So why would you invest in
Clojure?
Here’s a few reasons
Here’s a few reasons
Classes and Interfaces

• Minimize the accessibility of
classes and members

• In public classes, use
accessor methods, not public
fields

• Minimize mutability
Immutability
(def ages [10 20 30])
(def names ["Leo" "Liv" "Bruce"])
Immutability
(def ages [10 20 30])
(def names ["Leo" "Liv" "Bruce"])
(defrecord Person [fname age])
(def leo (->Person "Leo" 10))
;; {:fname "Leo", :age 10}
Immutability
(def ages [10 20 30])
(def names ["Leo" "Liv" "Bruce"])
(defrecord Person [fname age])
(map (fn [fname age]
(->Person fname age)) names ages)
;; ({:fname "Leo", :age 10}
;; {:fname "Liv", :age 20}
;; {:fname "Bruce", :age 30})
Immutability
(def ages [10 20 30])
(def names ["Leo" "Liv" "Bruce"])
(defrecord Person [fname age])
(map ->Person names ages)
;; ({:fname "Leo", :age 10}
;; {:fname "Liv", :age 20}
;; {:fname "Bruce", :age 30})
What if we want to add new
ages and names?
Adding new elements to vectors
(def new-ages (conj ages 40)) ;; [10 20 30 40]
ages ;; [10 20 30]
(def new-names (conj names "Gwen")) ;; ["Leo" "Liv"
"Bruce" "Gwen"]
names ;; ["Leo" "Liv" "Bruce"]
Is that slow?
Persistent data structures
(def xs ‘(0 1 2))
(def ys ‘(3 4 5))
Persistent data structures
(def xs ‘(0 1 2))
(def ys ‘(3 4 5))
(def zs (concat xs ys))
Persistent data structures
(def xs ‘(0 1 2))
(def ys ‘(3 4 5))
(def zs (concat xs ys))
Here’s a few reasons
Lambdas and Streams

• Prefer lambdas to anonymous
classes

• Prefer method references to
lambdas

• Favor the use of standard
functional interfaces
Prefer lambdas to anonymous classes
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
Prefer lambdas to anonymous classes
Collections.sort(names, (o1, o2) -> o1.compareTo(o2));
Collections.sort(names, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
Prefer method references to lambdas
Collections.sort(names, String::compareTo);
Collections.sort(names, (o1, o2) -> o1.compareTo(o2));
The Clojure way
(sort names) ;; ("Bruce" "Leo" “Liv”)
(sort-by #(count %) names) ;; ("Bruce" "Leo" “Liv")
(sort-by count names) ;; ("Bruce" "Leo" "Liv")
Anonymous functions
(sort-by (fn [s] (count s)) names) ;; ("Bruce" "Leo" "Liv")
(sort-by #(count %) names) ;; ("Bruce" "Leo" "Liv")
(sort-by count names) ;; ("Bruce" "Leo" "Liv")
Concurrency

• Synchronize access to shared
mutable data

• Avoid excessive
synchronization
Here’s a few reasons
Synchronise access to shared mutable data
class StopThread {
private static boolean stopRequested;
private static synchronized void requestStop() {
stopRequested = true;
}
private static synchronized boolean stopRequested() {
return stopRequested;
}
public static void example3() throws InterruptedException {
Thread backgroundThread = new Thread(() -> {
while (!stopRequested())
System.out.println("going....");
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
requestStop();
}
}
Synchronise access to shared mutable references
(def stop-requested (atom false))
(defn request-stop! []
(reset! stop-requested true))
(defn stop-requested? []
@stop-requested)
(defn example-3 []
(let [background-thread (java.lang.Thread. (fn []
(while (not (stop-requested?))
(prn "going..."))))]
(.start background-thread)
(Thread/sleep 1000)
(request-stop!)))
What about multiple shared
references?
STM - Software Transactional Memory
(def account-a (ref 100))
(def account-b (ref 250))
(defn transfer [amount from to]
(dosync
(alter from #(- % amount))
(alter to #(+ % amount))))
(transfer 25 account-a account-b)
@account-a ;; 75
@account-b ;; 275
Clojure makes it easy to do the
right thing
Let’s revisit example-3
(defn example-3 []
(let [background-thread (java.lang.Thread. (fn []
(while (not @stop-requested)
(prn "going..."))))]
(.start background-thread)
(Thread/sleep 1000)
(request-stop!)))
(defn example-3[]
(future
(while (not @stop-requested)
(prn "going...")))
(Thread/sleep 1000)
(request-stop!))
Concurrency with futures
(def doubler (partial * 2))
(defn service-a [n]
(future
(Thread/sleep 1000)
n))
(defn service-b [n]
(future
(Thread/sleep 1000)
(Math/pow n 2)))
(defn service-c [n]
(future
(Thread/sleep 1000)
(Math/pow n 3)))
(defn service-d [n]
(future
(Thread/sleep 1000)
(Math/pow n 4)))
(let [doubled (doubler @(service-a 10))]
(+ @(service-b doubled)
@(service-c doubled)
@(service-d doubled)))
;; Elapsed time: 4013.746558 msecs
(let [a (service-a 10)
doubled (doubler @a)
b (service-b doubled)
c (service-c doubled)
d (service-d doubled)]
(+ @b @c @d))
Concurrency with futures
(def doubler (partial * 2))
(defn service-a [n]
(future
(Thread/sleep 1000)
n))
(defn service-b [n]
(future
(Thread/sleep 1000)
(Math/pow n 2)))
(defn service-c [n]
(future
(Thread/sleep 1000)
(Math/pow n 3)))
(defn service-d [n]
(future
(Thread/sleep 1000)
(Math/pow n 4)))
(let [doubled (doubler @(service-a 10))]
(+ @(service-b doubled)
@(service-c doubled)
@(service-d doubled)))
;; Elapsed time: 4013.746558 msecs
(let [a (service-a 10)
doubled (doubler @a)
b (service-b doubled)
c (service-c doubled)
d (service-d doubled)]
(+ @b @c @d))
Blocks main thread!
Concurrency with CompletableFutures
static Integer doubler(Integer n) {
return 2 * n;
}
static CompletableFuture<Integer> serviceA(Integer n) {
return CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
return n;
});
}
static CompletableFuture<Integer> serviceB(Integer n) {
return CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
return Double.valueOf(Math.pow(n, 2)).intValue();
});
}
static CompletableFuture<Integer> serviceC(Integer n) {
return CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
return Double.valueOf(Math.pow(n, 3)).intValue();
});
}
Concurrency with CompletableFutures
final CompletableFuture<Integer> doubled = serviceA(10).thenApply(CompletableFutures::doubler);
final CompletableFuture<Integer> resultB = doubled.thenCompose(CompletableFutures::serviceB);
final CompletableFuture<Integer> resultC = doubled.thenCompose(CompletableFutures::serviceC);
CompletableFuture<Void> allFutures = CompletableFuture.allOf(resultB, resultC);
allFutures.whenComplete((v, ex) -> {
try {
System.out.println("Result: " + resultB.get() + " - " + resultC.get());
} catch (Exception e) {
}
});
Concurrency with CompletableFutures
final CompletableFuture<Integer> doubled = serviceA(10).thenApply(CompletableFutures::doubler);
final CompletableFuture<Integer> resultB = doubled.thenCompose(CompletableFutures::serviceB);
final CompletableFuture<Integer> resultC = doubled.thenCompose(CompletableFutures::serviceC);
CompletableFuture<Void> allFutures = CompletableFuture.allOf(resultB, resultC);
allFutures.whenComplete((v, ex) -> {
try {
System.out.println("Result: " + resultB.get() + " - " + resultC.get());
} catch (Exception e) {
}
});
What about Clojure?
What if?
;; Wouldn't it be great to be able to write:
(let [doubled (doubler (service-a 10))
b (service-b doubled)
c (service-c doubled)
d (service-d doubled)]
;; then once that's all done concurrently...
(+ b c d))
Concurrency with imminent
(require '[imminent.core :as i])
(defn service-a [n]
(i/future
(Thread/sleep 1000)
n))
(defn service-b [n]
(i/future
(Thread/sleep 1000)
(Math/pow n 2)))
(defn service-c [n]
(i/future
(Thread/sleep 1000)
(Math/pow n 3)))
(defn service-d [n]
(i/future
(Thread/sleep 1000)
(Math/pow n 4)))
Concurrency with imminent
(let [doubled (i/map (service-a 10) doubler)
b (i/bind doubled service-b)
c (i/bind doubled service-c)
d (i/bind doubled service-d)
result (i/sequence [b c d])]
(i/map result
(fn [[b c d]]
(+ b c d))))
;; Elapsed time: 2025.446899 msecs
Concurrency with imminent
(let [doubled (i/map (service-a 10) doubler)
b (i/bind doubled service-b)
c (i/bind doubled service-c)
d (i/bind doubled service-d)
result (i/sequence [b c d])]
(i/map result
(fn [[b c d]]
(+ b c d))))
;; Elapsed time: 2025.446899 msecs
Concurrency with imminent
(defn f-doubler [n]
(i/const-future (* n 2)))
(i/mdo [a (service-a 10)
doubled (f-doubler a)
b (service-b doubled)
c (service-c doubled)
d (service-d doubled)]
(i/return (+ b c d)))
Concurrency with imminent
(bind
(service-a 10)
(fn* ([a]
(bind
(f-doubler a)
(fn* ([doubled]
(bind
(service-b doubled)
(fn* ([b]
(bind
(service-c doubled) (fn* ([c]
(bind
(service-d doubled)
(fn* ([d]
(i/return (+ b c d))))))))))))))))))
Concurrency with imminent
(bind
(service-a 10)
(fn* ([a]
(bind
(f-doubler a)
(fn* ([doubled]
(bind
(service-b doubled)
(fn* ([b]
(bind
(service-c doubled) (fn* ([c]
(bind
(service-d doubled)
(fn* ([d]
(i/return (+ b c d))))))))))))))))))
;; Elapsed time: 4017.578654 msecs
Concurrency with imminent
(def a+ (i/alift +))
(i/mdo [a (service-a 10)
doubled (f-doubler a)]
(a+ (service-b doubled)
(service-c doubled)
(service-d doubled)))
;; Elapsed time: 2010.171729 msecs
Concurrency with imminent
(def a+ (i/alift +))
(i/mdo [a (service-a 10)
doubled (f-doubler a)]
(a+ (service-b doubled)
(service-c doubled)
(service-d doubled)))
;; Elapsed time: 2010.171729 msecs
What’s with map, bind and
alift?
The algebra of library design
i/map => Functor
i/bind => Monad
i/alift => Applicative
References
• Clojure Reactive Programming - http://bit.ly/cljRp
• Imminent - http://bit.ly/immi-clj
• The Algebra of Library Design - http://bit.ly/2HBBJwJ
• Purely Functional Data Structures - https://amzn.to/2zGZizS
• Java 8 CompletableFuture - http://bit.ly/j8Future
• Java 8 Streams - http://bit.ly/j8stream
• Category Theory - http://amzn.to/1NfL08U
Thank you!
Leonardo Borges

@leonardo_borges

www.leonardoborges.com

www.recordpoint.com
:clojure/south - São Paulo, 2019

More Related Content

KEY
Clojure Intro
thnetos
 
PDF
Clojure for Java developers - Stockholm
Jan Kronquist
 
PDF
What can be done with Java, but should better be done with Erlang (@pavlobaron)
Pavlo Baron
 
PDF
An introduction to Rust: the modern programming language to develop safe and ...
Claudio Capobianco
 
PDF
Clojure, Plain and Simple
Ben Mabey
 
PPTX
Introduction to Rust language programming
Rodolfo Finochietti
 
PDF
The Rust Programming Language: an Overview
Roberto Casadei
 
PDF
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Chris Richardson
 
Clojure Intro
thnetos
 
Clojure for Java developers - Stockholm
Jan Kronquist
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
Pavlo Baron
 
An introduction to Rust: the modern programming language to develop safe and ...
Claudio Capobianco
 
Clojure, Plain and Simple
Ben Mabey
 
Introduction to Rust language programming
Rodolfo Finochietti
 
The Rust Programming Language: an Overview
Roberto Casadei
 
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Chris Richardson
 

What's hot (20)

PDF
JavaOne 2013 - Clojure for Java Developers
Jan Kronquist
 
PDF
If You Think You Can Stay Away from Functional Programming, You Are Wrong
Mario Fusco
 
PDF
(Greach 2015) Dsl'ing your Groovy
Alonso Torres
 
KEY
(map Clojure everyday-tasks)
Jacek Laskowski
 
PDF
A Sceptical Guide to Functional Programming
Garth Gilmour
 
PDF
Why rust?
Mats Kindahl
 
PDF
Concurrency Concepts in Java
Doug Hawkins
 
PDF
C++ Boot Camp Part 2
Jesse Talavera-Greenberg
 
ODP
Turtle Graphics in Groovy
Jim Driscoll
 
PPTX
Zero-Overhead Metaprogramming: Reflection and Metaobject Protocols Fast and w...
Stefan Marr
 
PDF
groovy rules
Paul King
 
PDF
core.logic introduction
Norman Richards
 
PPTX
Building High-Performance Language Implementations With Low Effort
Stefan Marr
 
PDF
Clojure made-simple - John Stevenson
JAX London
 
PDF
C# - What's next
Christian Nagel
 
PDF
Logic programming a ruby perspective
Norman Richards
 
PDF
OracleCode One 2018: Java 5, 6, 7, 8, 9, 10, 11: What Did You Miss?
Henri Tremblay
 
PDF
Hw09 Hadoop + Clojure
Cloudera, Inc.
 
PPTX
Return of c++
Yongwei Wu
 
PDF
JavaScript - new features in ECMAScript 6
Solution4Future
 
JavaOne 2013 - Clojure for Java Developers
Jan Kronquist
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
Mario Fusco
 
(Greach 2015) Dsl'ing your Groovy
Alonso Torres
 
(map Clojure everyday-tasks)
Jacek Laskowski
 
A Sceptical Guide to Functional Programming
Garth Gilmour
 
Why rust?
Mats Kindahl
 
Concurrency Concepts in Java
Doug Hawkins
 
C++ Boot Camp Part 2
Jesse Talavera-Greenberg
 
Turtle Graphics in Groovy
Jim Driscoll
 
Zero-Overhead Metaprogramming: Reflection and Metaobject Protocols Fast and w...
Stefan Marr
 
groovy rules
Paul King
 
core.logic introduction
Norman Richards
 
Building High-Performance Language Implementations With Low Effort
Stefan Marr
 
Clojure made-simple - John Stevenson
JAX London
 
C# - What's next
Christian Nagel
 
Logic programming a ruby perspective
Norman Richards
 
OracleCode One 2018: Java 5, 6, 7, 8, 9, 10, 11: What Did You Miss?
Henri Tremblay
 
Hw09 Hadoop + Clojure
Cloudera, Inc.
 
Return of c++
Yongwei Wu
 
JavaScript - new features in ECMAScript 6
Solution4Future
 
Ad

Similar to From Java to Parellel Clojure - Clojure South 2019 (20)

PPTX
Clojure And Swing
Skills Matter
 
PDF
Clojure 1.1 And Beyond
Mike Fogus
 
ODP
Getting started with Clojure
John Stevenson
 
PDF
Exploring Clojurescript
Luke Donnet
 
PDF
Pune Clojure Course Outline
Baishampayan Ghose
 
PDF
Lobos Introduction
Nicolas Buduroi
 
PDF
ClojureScript for the web
Michiel Borkent
 
PDF
Introduction to clojure
Abbas Raza
 
PDF
Clojure for Java developers
John Stevenson
 
PPT
Clojure concurrency
Alex Navis
 
PDF
Kotlin @ Coupang Backend 2017
Sunghyouk Bae
 
PDF
Clojure+ClojureScript Webapps
Falko Riemenschneider
 
PDF
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
bobmcwhirter
 
PDF
Coding in Style
scalaconfjp
 
PDF
Torquebox OSCON Java 2011
tobiascrawley
 
PDF
ClojureScript: The Good Parts
Kent Ohashi
 
PDF
Practical REPL-driven Development with Clojure
Kent Ohashi
 
PDF
A Survey of Concurrency Constructs
Ted Leung
 
PDF
Spock: Test Well and Prosper
Ken Kousen
 
PDF
Clojure - A new Lisp
elliando dias
 
Clojure And Swing
Skills Matter
 
Clojure 1.1 And Beyond
Mike Fogus
 
Getting started with Clojure
John Stevenson
 
Exploring Clojurescript
Luke Donnet
 
Pune Clojure Course Outline
Baishampayan Ghose
 
Lobos Introduction
Nicolas Buduroi
 
ClojureScript for the web
Michiel Borkent
 
Introduction to clojure
Abbas Raza
 
Clojure for Java developers
John Stevenson
 
Clojure concurrency
Alex Navis
 
Kotlin @ Coupang Backend 2017
Sunghyouk Bae
 
Clojure+ClojureScript Webapps
Falko Riemenschneider
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
bobmcwhirter
 
Coding in Style
scalaconfjp
 
Torquebox OSCON Java 2011
tobiascrawley
 
ClojureScript: The Good Parts
Kent Ohashi
 
Practical REPL-driven Development with Clojure
Kent Ohashi
 
A Survey of Concurrency Constructs
Ted Leung
 
Spock: Test Well and Prosper
Ken Kousen
 
Clojure - A new Lisp
elliando dias
 
Ad

More from Leonardo Borges (20)

PDF
Realtime collaboration with Clojure - EuroClojure - Barcelona, 2015
Leonardo Borges
 
PDF
Parametricity - #cljsyd - May, 2015
Leonardo Borges
 
PDF
The algebra of library design
Leonardo Borges
 
PDF
Futures e abstração - QCon São Paulo 2015
Leonardo Borges
 
PDF
Functional Reactive Programming / Compositional Event Systems
Leonardo Borges
 
PDF
High Performance web apps in Om, React and ClojureScript
Leonardo Borges
 
PDF
Programação functional reativa: lidando com código assíncrono
Leonardo Borges
 
PDF
Monads in Clojure
Leonardo Borges
 
PDF
Clojure Macros Workshop: LambdaJam 2013 / CUFP 2013
Leonardo Borges
 
PDF
Intro to Clojure's core.async
Leonardo Borges
 
PDF
Functional Reactive Programming in Clojurescript
Leonardo Borges
 
PDF
Clojure/West 2013 in 30 mins
Leonardo Borges
 
PDF
Clojure Reducers / clj-syd Aug 2012
Leonardo Borges
 
PDF
The many facets of code reuse in JavaScript
Leonardo Borges
 
PDF
Continuation Passing Style and Macros in Clojure - Jan 2012
Leonardo Borges
 
PDF
Heroku addons development - Nov 2011
Leonardo Borges
 
PDF
Clouds against the Floods (RubyConfBR2011)
Leonardo Borges
 
KEY
Clouds Against the Floods
Leonardo Borges
 
KEY
Arel in Rails 3
Leonardo Borges
 
PDF
Testing with Spring
Leonardo Borges
 
Realtime collaboration with Clojure - EuroClojure - Barcelona, 2015
Leonardo Borges
 
Parametricity - #cljsyd - May, 2015
Leonardo Borges
 
The algebra of library design
Leonardo Borges
 
Futures e abstração - QCon São Paulo 2015
Leonardo Borges
 
Functional Reactive Programming / Compositional Event Systems
Leonardo Borges
 
High Performance web apps in Om, React and ClojureScript
Leonardo Borges
 
Programação functional reativa: lidando com código assíncrono
Leonardo Borges
 
Monads in Clojure
Leonardo Borges
 
Clojure Macros Workshop: LambdaJam 2013 / CUFP 2013
Leonardo Borges
 
Intro to Clojure's core.async
Leonardo Borges
 
Functional Reactive Programming in Clojurescript
Leonardo Borges
 
Clojure/West 2013 in 30 mins
Leonardo Borges
 
Clojure Reducers / clj-syd Aug 2012
Leonardo Borges
 
The many facets of code reuse in JavaScript
Leonardo Borges
 
Continuation Passing Style and Macros in Clojure - Jan 2012
Leonardo Borges
 
Heroku addons development - Nov 2011
Leonardo Borges
 
Clouds against the Floods (RubyConfBR2011)
Leonardo Borges
 
Clouds Against the Floods
Leonardo Borges
 
Arel in Rails 3
Leonardo Borges
 
Testing with Spring
Leonardo Borges
 

Recently uploaded (20)

PDF
49785682629390197565_LRN3014_Migrating_the_Beast.pdf
Abilash868456
 
PDF
QAware_Mario-Leander_Reimer_Architecting and Building a K8s-based AI Platform...
QAware GmbH
 
PDF
Teaching Reproducibility and Embracing Variability: From Floating-Point Exper...
University of Rennes, INSA Rennes, Inria/IRISA, CNRS
 
PDF
Community & News Update Q2 Meet Up 2025
VictoriaMetrics
 
PDF
PFAS Reporting Requirements 2026 Are You Submission Ready Certivo.pdf
Certivo Inc
 
PPTX
slidesgo-unlocking-the-code-the-dynamic-dance-of-variables-and-constants-2024...
kr2589474
 
PPT
Activate_Methodology_Summary presentatio
annapureddyn
 
PDF
Appium Automation Testing Tutorial PDF: Learn Mobile Testing in 7 Days
jamescantor38
 
PDF
lesson-2-rules-of-netiquette.pdf.bshhsjdj
jasmenrojas249
 
PDF
ShowUs: Pharo Stream Deck (ESUG 2025, Gdansk)
ESUG
 
PPTX
Explanation about Structures in C language.pptx
Veeral Rathod
 
PPTX
AI-Ready Handoff: Auto-Summaries & Draft Emails from MQL to Slack in One Flow
bbedford2
 
PDF
Protecting the Digital World Cyber Securit
dnthakkar16
 
PPTX
Presentation about variables and constant.pptx
safalsingh810
 
PDF
IEEE-CS Tech Predictions, SWEBOK and Quantum Software: Towards Q-SWEBOK
Hironori Washizaki
 
PDF
The Role of Automation and AI in EHS Management for Data Centers.pdf
TECH EHS Solution
 
PPTX
TestNG for Java Testing and Automation testing
ssuser0213cb
 
PDF
Jenkins: An open-source automation server powering CI/CD Automation
SaikatBasu37
 
PPTX
Visualising Data with Scatterplots in IBM SPSS Statistics.pptx
Version 1 Analytics
 
PDF
Why Use Open Source Reporting Tools for Business Intelligence.pdf
Varsha Nayak
 
49785682629390197565_LRN3014_Migrating_the_Beast.pdf
Abilash868456
 
QAware_Mario-Leander_Reimer_Architecting and Building a K8s-based AI Platform...
QAware GmbH
 
Teaching Reproducibility and Embracing Variability: From Floating-Point Exper...
University of Rennes, INSA Rennes, Inria/IRISA, CNRS
 
Community & News Update Q2 Meet Up 2025
VictoriaMetrics
 
PFAS Reporting Requirements 2026 Are You Submission Ready Certivo.pdf
Certivo Inc
 
slidesgo-unlocking-the-code-the-dynamic-dance-of-variables-and-constants-2024...
kr2589474
 
Activate_Methodology_Summary presentatio
annapureddyn
 
Appium Automation Testing Tutorial PDF: Learn Mobile Testing in 7 Days
jamescantor38
 
lesson-2-rules-of-netiquette.pdf.bshhsjdj
jasmenrojas249
 
ShowUs: Pharo Stream Deck (ESUG 2025, Gdansk)
ESUG
 
Explanation about Structures in C language.pptx
Veeral Rathod
 
AI-Ready Handoff: Auto-Summaries & Draft Emails from MQL to Slack in One Flow
bbedford2
 
Protecting the Digital World Cyber Securit
dnthakkar16
 
Presentation about variables and constant.pptx
safalsingh810
 
IEEE-CS Tech Predictions, SWEBOK and Quantum Software: Towards Q-SWEBOK
Hironori Washizaki
 
The Role of Automation and AI in EHS Management for Data Centers.pdf
TECH EHS Solution
 
TestNG for Java Testing and Automation testing
ssuser0213cb
 
Jenkins: An open-source automation server powering CI/CD Automation
SaikatBasu37
 
Visualising Data with Scatterplots in IBM SPSS Statistics.pptx
Version 1 Analytics
 
Why Use Open Source Reporting Tools for Business Intelligence.pdf
Varsha Nayak
 

From Java to Parellel Clojure - Clojure South 2019

  • 1. :clojure/south - São Paulo, 2019 From Java to parallel Clojure Leonardo Borges @leonardo_borges www.leonardoborges.com www.recordpoint.com
  • 2. A bit about me • Head of Engineering at RecordPoint • Founder of the Sydney Clojure User Group • Open-source contributor • Author of bouncer and imminent • Author of Clojure Reactive Programming
  • 3. A bit about me • 2nd edition is out now!
  • 5. What we’ll talk about • Being a Lisp on the JVM • Functional Programming strengths • Concurrency and parallelism
  • 6. Java has come a long way… • ForkJoin; • Lambda Expressions; • Method References; • CompletableFutures; • JShell; • Reactive Streams / Stream API; • …and more!
  • 7. So why would you invest in Clojure?
  • 8. Here’s a few reasons
  • 9. Here’s a few reasons Classes and Interfaces • Minimize the accessibility of classes and members • In public classes, use accessor methods, not public fields • Minimize mutability
  • 10. Immutability (def ages [10 20 30]) (def names ["Leo" "Liv" "Bruce"])
  • 11. Immutability (def ages [10 20 30]) (def names ["Leo" "Liv" "Bruce"]) (defrecord Person [fname age]) (def leo (->Person "Leo" 10)) ;; {:fname "Leo", :age 10}
  • 12. Immutability (def ages [10 20 30]) (def names ["Leo" "Liv" "Bruce"]) (defrecord Person [fname age]) (map (fn [fname age] (->Person fname age)) names ages) ;; ({:fname "Leo", :age 10} ;; {:fname "Liv", :age 20} ;; {:fname "Bruce", :age 30})
  • 13. Immutability (def ages [10 20 30]) (def names ["Leo" "Liv" "Bruce"]) (defrecord Person [fname age]) (map ->Person names ages) ;; ({:fname "Leo", :age 10} ;; {:fname "Liv", :age 20} ;; {:fname "Bruce", :age 30})
  • 14. What if we want to add new ages and names?
  • 15. Adding new elements to vectors (def new-ages (conj ages 40)) ;; [10 20 30 40] ages ;; [10 20 30] (def new-names (conj names "Gwen")) ;; ["Leo" "Liv" "Bruce" "Gwen"] names ;; ["Leo" "Liv" "Bruce"]
  • 17. Persistent data structures (def xs ‘(0 1 2)) (def ys ‘(3 4 5))
  • 18. Persistent data structures (def xs ‘(0 1 2)) (def ys ‘(3 4 5)) (def zs (concat xs ys))
  • 19. Persistent data structures (def xs ‘(0 1 2)) (def ys ‘(3 4 5)) (def zs (concat xs ys))
  • 20. Here’s a few reasons Lambdas and Streams • Prefer lambdas to anonymous classes • Prefer method references to lambdas • Favor the use of standard functional interfaces
  • 21. Prefer lambdas to anonymous classes Collections.sort(names, new Comparator<String>() { @Override public int compare(String o1, String o2) { return o1.compareTo(o2); } });
  • 22. Prefer lambdas to anonymous classes Collections.sort(names, (o1, o2) -> o1.compareTo(o2)); Collections.sort(names, new Comparator<String>() { @Override public int compare(String o1, String o2) { return o1.compareTo(o2); } });
  • 23. Prefer method references to lambdas Collections.sort(names, String::compareTo); Collections.sort(names, (o1, o2) -> o1.compareTo(o2));
  • 24. The Clojure way (sort names) ;; ("Bruce" "Leo" “Liv”) (sort-by #(count %) names) ;; ("Bruce" "Leo" “Liv") (sort-by count names) ;; ("Bruce" "Leo" "Liv")
  • 25. Anonymous functions (sort-by (fn [s] (count s)) names) ;; ("Bruce" "Leo" "Liv") (sort-by #(count %) names) ;; ("Bruce" "Leo" "Liv") (sort-by count names) ;; ("Bruce" "Leo" "Liv")
  • 26. Concurrency • Synchronize access to shared mutable data • Avoid excessive synchronization Here’s a few reasons
  • 27. Synchronise access to shared mutable data class StopThread { private static boolean stopRequested; private static synchronized void requestStop() { stopRequested = true; } private static synchronized boolean stopRequested() { return stopRequested; } public static void example3() throws InterruptedException { Thread backgroundThread = new Thread(() -> { while (!stopRequested()) System.out.println("going...."); }); backgroundThread.start(); TimeUnit.SECONDS.sleep(1); requestStop(); } }
  • 28. Synchronise access to shared mutable references (def stop-requested (atom false)) (defn request-stop! [] (reset! stop-requested true)) (defn stop-requested? [] @stop-requested) (defn example-3 [] (let [background-thread (java.lang.Thread. (fn [] (while (not (stop-requested?)) (prn "going..."))))] (.start background-thread) (Thread/sleep 1000) (request-stop!)))
  • 29. What about multiple shared references?
  • 30. STM - Software Transactional Memory (def account-a (ref 100)) (def account-b (ref 250)) (defn transfer [amount from to] (dosync (alter from #(- % amount)) (alter to #(+ % amount)))) (transfer 25 account-a account-b) @account-a ;; 75 @account-b ;; 275
  • 31. Clojure makes it easy to do the right thing
  • 33. (defn example-3 [] (let [background-thread (java.lang.Thread. (fn [] (while (not @stop-requested) (prn "going..."))))] (.start background-thread) (Thread/sleep 1000) (request-stop!)))
  • 34. (defn example-3[] (future (while (not @stop-requested) (prn "going..."))) (Thread/sleep 1000) (request-stop!))
  • 35. Concurrency with futures (def doubler (partial * 2)) (defn service-a [n] (future (Thread/sleep 1000) n)) (defn service-b [n] (future (Thread/sleep 1000) (Math/pow n 2))) (defn service-c [n] (future (Thread/sleep 1000) (Math/pow n 3))) (defn service-d [n] (future (Thread/sleep 1000) (Math/pow n 4))) (let [doubled (doubler @(service-a 10))] (+ @(service-b doubled) @(service-c doubled) @(service-d doubled))) ;; Elapsed time: 4013.746558 msecs (let [a (service-a 10) doubled (doubler @a) b (service-b doubled) c (service-c doubled) d (service-d doubled)] (+ @b @c @d))
  • 36. Concurrency with futures (def doubler (partial * 2)) (defn service-a [n] (future (Thread/sleep 1000) n)) (defn service-b [n] (future (Thread/sleep 1000) (Math/pow n 2))) (defn service-c [n] (future (Thread/sleep 1000) (Math/pow n 3))) (defn service-d [n] (future (Thread/sleep 1000) (Math/pow n 4))) (let [doubled (doubler @(service-a 10))] (+ @(service-b doubled) @(service-c doubled) @(service-d doubled))) ;; Elapsed time: 4013.746558 msecs (let [a (service-a 10) doubled (doubler @a) b (service-b doubled) c (service-c doubled) d (service-d doubled)] (+ @b @c @d)) Blocks main thread!
  • 37. Concurrency with CompletableFutures static Integer doubler(Integer n) { return 2 * n; } static CompletableFuture<Integer> serviceA(Integer n) { return CompletableFuture.supplyAsync(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { } return n; }); } static CompletableFuture<Integer> serviceB(Integer n) { return CompletableFuture.supplyAsync(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { } return Double.valueOf(Math.pow(n, 2)).intValue(); }); } static CompletableFuture<Integer> serviceC(Integer n) { return CompletableFuture.supplyAsync(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { } return Double.valueOf(Math.pow(n, 3)).intValue(); }); }
  • 38. Concurrency with CompletableFutures final CompletableFuture<Integer> doubled = serviceA(10).thenApply(CompletableFutures::doubler); final CompletableFuture<Integer> resultB = doubled.thenCompose(CompletableFutures::serviceB); final CompletableFuture<Integer> resultC = doubled.thenCompose(CompletableFutures::serviceC); CompletableFuture<Void> allFutures = CompletableFuture.allOf(resultB, resultC); allFutures.whenComplete((v, ex) -> { try { System.out.println("Result: " + resultB.get() + " - " + resultC.get()); } catch (Exception e) { } });
  • 39. Concurrency with CompletableFutures final CompletableFuture<Integer> doubled = serviceA(10).thenApply(CompletableFutures::doubler); final CompletableFuture<Integer> resultB = doubled.thenCompose(CompletableFutures::serviceB); final CompletableFuture<Integer> resultC = doubled.thenCompose(CompletableFutures::serviceC); CompletableFuture<Void> allFutures = CompletableFuture.allOf(resultB, resultC); allFutures.whenComplete((v, ex) -> { try { System.out.println("Result: " + resultB.get() + " - " + resultC.get()); } catch (Exception e) { } });
  • 41. What if? ;; Wouldn't it be great to be able to write: (let [doubled (doubler (service-a 10)) b (service-b doubled) c (service-c doubled) d (service-d doubled)] ;; then once that's all done concurrently... (+ b c d))
  • 42. Concurrency with imminent (require '[imminent.core :as i]) (defn service-a [n] (i/future (Thread/sleep 1000) n)) (defn service-b [n] (i/future (Thread/sleep 1000) (Math/pow n 2))) (defn service-c [n] (i/future (Thread/sleep 1000) (Math/pow n 3))) (defn service-d [n] (i/future (Thread/sleep 1000) (Math/pow n 4)))
  • 43. Concurrency with imminent (let [doubled (i/map (service-a 10) doubler) b (i/bind doubled service-b) c (i/bind doubled service-c) d (i/bind doubled service-d) result (i/sequence [b c d])] (i/map result (fn [[b c d]] (+ b c d)))) ;; Elapsed time: 2025.446899 msecs
  • 44. Concurrency with imminent (let [doubled (i/map (service-a 10) doubler) b (i/bind doubled service-b) c (i/bind doubled service-c) d (i/bind doubled service-d) result (i/sequence [b c d])] (i/map result (fn [[b c d]] (+ b c d)))) ;; Elapsed time: 2025.446899 msecs
  • 45. Concurrency with imminent (defn f-doubler [n] (i/const-future (* n 2))) (i/mdo [a (service-a 10) doubled (f-doubler a) b (service-b doubled) c (service-c doubled) d (service-d doubled)] (i/return (+ b c d)))
  • 46. Concurrency with imminent (bind (service-a 10) (fn* ([a] (bind (f-doubler a) (fn* ([doubled] (bind (service-b doubled) (fn* ([b] (bind (service-c doubled) (fn* ([c] (bind (service-d doubled) (fn* ([d] (i/return (+ b c d))))))))))))))))))
  • 47. Concurrency with imminent (bind (service-a 10) (fn* ([a] (bind (f-doubler a) (fn* ([doubled] (bind (service-b doubled) (fn* ([b] (bind (service-c doubled) (fn* ([c] (bind (service-d doubled) (fn* ([d] (i/return (+ b c d)))))))))))))))))) ;; Elapsed time: 4017.578654 msecs
  • 48. Concurrency with imminent (def a+ (i/alift +)) (i/mdo [a (service-a 10) doubled (f-doubler a)] (a+ (service-b doubled) (service-c doubled) (service-d doubled))) ;; Elapsed time: 2010.171729 msecs
  • 49. Concurrency with imminent (def a+ (i/alift +)) (i/mdo [a (service-a 10) doubled (f-doubler a)] (a+ (service-b doubled) (service-c doubled) (service-d doubled))) ;; Elapsed time: 2010.171729 msecs
  • 50. What’s with map, bind and alift?
  • 51. The algebra of library design i/map => Functor i/bind => Monad i/alift => Applicative
  • 52. References • Clojure Reactive Programming - http://bit.ly/cljRp • Imminent - http://bit.ly/immi-clj • The Algebra of Library Design - http://bit.ly/2HBBJwJ • Purely Functional Data Structures - https://amzn.to/2zGZizS • Java 8 CompletableFuture - http://bit.ly/j8Future • Java 8 Streams - http://bit.ly/j8stream • Category Theory - http://amzn.to/1NfL08U