SlideShare una empresa de Scribd 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

Más contenido relacionado

La actualidad más candente

JavaOne 2013 - Clojure for Java Developers
JavaOne 2013 - Clojure for Java DevelopersJavaOne 2013 - Clojure for Java Developers
JavaOne 2013 - Clojure for Java Developers
Jan Kronquist
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongMario Fusco
 
(Greach 2015) Dsl'ing your Groovy
(Greach 2015) Dsl'ing your Groovy(Greach 2015) Dsl'ing your Groovy
(Greach 2015) Dsl'ing your Groovy
Alonso Torres
 
(map Clojure everyday-tasks)
(map Clojure everyday-tasks)(map Clojure everyday-tasks)
(map Clojure everyday-tasks)
Jacek Laskowski
 
A Sceptical Guide to Functional Programming
A Sceptical Guide to Functional ProgrammingA Sceptical Guide to Functional Programming
A Sceptical Guide to Functional ProgrammingGarth Gilmour
 
Why rust?
Why rust?Why rust?
Why rust?
Mats Kindahl
 
Concurrency Concepts in Java
Concurrency Concepts in JavaConcurrency Concepts in Java
Concurrency Concepts in Java
Doug Hawkins
 
Turtle Graphics in Groovy
Turtle Graphics in GroovyTurtle Graphics in Groovy
Turtle Graphics in Groovy
Jim Driscoll
 
Zero-Overhead Metaprogramming: Reflection and Metaobject Protocols Fast and w...
Zero-Overhead Metaprogramming: Reflection and Metaobject Protocols Fast and w...Zero-Overhead Metaprogramming: Reflection and Metaobject Protocols Fast and w...
Zero-Overhead Metaprogramming: Reflection and Metaobject Protocols Fast and w...
Stefan Marr
 
groovy rules
groovy rulesgroovy rules
groovy rulesPaul King
 
core.logic introduction
core.logic introductioncore.logic introduction
core.logic introduction
Norman Richards
 
Building High-Performance Language Implementations With Low Effort
Building High-Performance Language Implementations With Low EffortBuilding High-Performance Language Implementations With Low Effort
Building High-Performance Language Implementations With Low Effort
Stefan Marr
 
Clojure made-simple - John Stevenson
Clojure made-simple - John StevensonClojure made-simple - John Stevenson
Clojure made-simple - John Stevenson
JAX London
 
C# - What's next
C# - What's nextC# - What's next
C# - What's next
Christian Nagel
 
Logic programming a ruby perspective
Logic programming a ruby perspectiveLogic programming a ruby perspective
Logic programming a ruby perspective
Norman Richards
 
OracleCode One 2018: Java 5, 6, 7, 8, 9, 10, 11: What Did You Miss?
OracleCode One 2018: Java 5, 6, 7, 8, 9, 10, 11: What Did You Miss?OracleCode One 2018: Java 5, 6, 7, 8, 9, 10, 11: What Did You Miss?
OracleCode One 2018: Java 5, 6, 7, 8, 9, 10, 11: What Did You Miss?
Henri Tremblay
 
Return of c++
Return of c++Return of c++
Return of c++
Yongwei Wu
 
JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6Solution4Future
 

La actualidad más candente (20)

JavaOne 2013 - Clojure for Java Developers
JavaOne 2013 - Clojure for Java DevelopersJavaOne 2013 - Clojure for Java Developers
JavaOne 2013 - Clojure for Java Developers
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are Wrong
 
(Greach 2015) Dsl'ing your Groovy
(Greach 2015) Dsl'ing your Groovy(Greach 2015) Dsl'ing your Groovy
(Greach 2015) Dsl'ing your Groovy
 
(map Clojure everyday-tasks)
(map Clojure everyday-tasks)(map Clojure everyday-tasks)
(map Clojure everyday-tasks)
 
A Sceptical Guide to Functional Programming
A Sceptical Guide to Functional ProgrammingA Sceptical Guide to Functional Programming
A Sceptical Guide to Functional Programming
 
Why rust?
Why rust?Why rust?
Why rust?
 
Concurrency Concepts in Java
Concurrency Concepts in JavaConcurrency Concepts in Java
Concurrency Concepts in Java
 
C++ Boot Camp Part 2
C++ Boot Camp Part 2C++ Boot Camp Part 2
C++ Boot Camp Part 2
 
Turtle Graphics in Groovy
Turtle Graphics in GroovyTurtle Graphics in Groovy
Turtle Graphics in Groovy
 
Zero-Overhead Metaprogramming: Reflection and Metaobject Protocols Fast and w...
Zero-Overhead Metaprogramming: Reflection and Metaobject Protocols Fast and w...Zero-Overhead Metaprogramming: Reflection and Metaobject Protocols Fast and w...
Zero-Overhead Metaprogramming: Reflection and Metaobject Protocols Fast and w...
 
groovy rules
groovy rulesgroovy rules
groovy rules
 
core.logic introduction
core.logic introductioncore.logic introduction
core.logic introduction
 
Building High-Performance Language Implementations With Low Effort
Building High-Performance Language Implementations With Low EffortBuilding High-Performance Language Implementations With Low Effort
Building High-Performance Language Implementations With Low Effort
 
Clojure made-simple - John Stevenson
Clojure made-simple - John StevensonClojure made-simple - John Stevenson
Clojure made-simple - John Stevenson
 
C# - What's next
C# - What's nextC# - What's next
C# - What's next
 
Logic programming a ruby perspective
Logic programming a ruby perspectiveLogic programming a ruby perspective
Logic programming a ruby perspective
 
OracleCode One 2018: Java 5, 6, 7, 8, 9, 10, 11: What Did You Miss?
OracleCode One 2018: Java 5, 6, 7, 8, 9, 10, 11: What Did You Miss?OracleCode One 2018: Java 5, 6, 7, 8, 9, 10, 11: What Did You Miss?
OracleCode One 2018: Java 5, 6, 7, 8, 9, 10, 11: What Did You Miss?
 
Hw09 Hadoop + Clojure
Hw09   Hadoop + ClojureHw09   Hadoop + Clojure
Hw09 Hadoop + Clojure
 
Return of c++
Return of c++Return of c++
Return of c++
 
JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6JavaScript - new features in ECMAScript 6
JavaScript - new features in ECMAScript 6
 

Similar a From Java to Parellel Clojure - Clojure South 2019

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

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

Clojure And Swing
Clojure And SwingClojure And Swing
Clojure And Swing
 
Clojure 1.1 And Beyond
Clojure 1.1 And BeyondClojure 1.1 And Beyond
Clojure 1.1 And Beyond
 
Getting started with Clojure
Getting started with ClojureGetting started with Clojure
Getting started with Clojure
 
Exploring Clojurescript
Exploring ClojurescriptExploring Clojurescript
Exploring Clojurescript
 
Pune Clojure Course Outline
Pune Clojure Course OutlinePune Clojure Course Outline
Pune Clojure Course Outline
 
Lobos Introduction
Lobos IntroductionLobos Introduction
Lobos Introduction
 
ClojureScript for the web
ClojureScript for the webClojureScript for the web
ClojureScript for the web
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojure
 
Clojure for Java developers
Clojure for Java developersClojure for Java developers
Clojure for Java developers
 
Clojure concurrency
Clojure concurrencyClojure concurrency
Clojure concurrency
 
Kotlin @ Coupang Backend 2017
Kotlin @ Coupang Backend 2017Kotlin @ Coupang Backend 2017
Kotlin @ Coupang Backend 2017
 
Clojure+ClojureScript Webapps
Clojure+ClojureScript WebappsClojure+ClojureScript Webapps
Clojure+ClojureScript Webapps
 
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...TorqueBox: The beauty of Ruby with the power of JBoss.  Presented at Devnexus...
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
 
Coding in Style
Coding in StyleCoding in Style
Coding in Style
 
Torquebox OSCON Java 2011
Torquebox OSCON Java 2011Torquebox OSCON Java 2011
Torquebox OSCON Java 2011
 
ClojureScript: The Good Parts
ClojureScript: The Good PartsClojureScript: The Good Parts
ClojureScript: The Good Parts
 
Practical REPL-driven Development with Clojure
Practical REPL-driven Development with ClojurePractical REPL-driven Development with Clojure
Practical REPL-driven Development with Clojure
 
A Survey of Concurrency Constructs
A Survey of Concurrency ConstructsA Survey of Concurrency Constructs
A Survey of Concurrency Constructs
 
Spock: Test Well and Prosper
Spock: Test Well and ProsperSpock: Test Well and Prosper
Spock: Test Well and Prosper
 
Clojure - A new Lisp
Clojure - A new LispClojure - A new Lisp
Clojure - A new Lisp
 

Más de Leonardo Borges

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

Más de Leonardo Borges (20)

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

Último

APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni García
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
Philip Schwarz
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Crescat
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
Deuglo Infosystem Pvt Ltd
 
Transform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR SolutionsTransform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR Solutions
TheSMSPoint
 
AI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website CreatorAI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website Creator
Google
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
Ayan Halder
 
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissancesAtelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Neo4j
 
Launch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in MinutesLaunch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in Minutes
Roshan Dwivedi
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
Łukasz Chruściel
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
Google
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Mind IT Systems
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdfVitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke
 
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
Aftab Hussain
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
lorraineandreiamcidl
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
Donna Lenk
 

Último (20)

APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
 
Empowering Growth with Best Software Development Company in Noida - Deuglo
Empowering Growth with Best Software  Development Company in Noida - DeugloEmpowering Growth with Best Software  Development Company in Noida - Deuglo
Empowering Growth with Best Software Development Company in Noida - Deuglo
 
Transform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR SolutionsTransform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR Solutions
 
AI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website CreatorAI Genie Review: World’s First Open AI WordPress Website Creator
AI Genie Review: World’s First Open AI WordPress Website Creator
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
 
Atelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissancesAtelier - Innover avec l’IA Générative et les graphes de connaissances
Atelier - Innover avec l’IA Générative et les graphes de connaissances
 
Launch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in MinutesLaunch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in Minutes
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
 
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
Custom Healthcare Software for Managing Chronic Conditions and Remote Patient...
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdfVitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdf
 
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of CodeA Study of Variable-Role-based Feature Enrichment in Neural Models of Code
A Study of Variable-Role-based Feature Enrichment in Neural Models of Code
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
 
Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"Navigating the Metaverse: A Journey into Virtual Evolution"
Navigating the Metaverse: A Journey into Virtual Evolution"
 

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