Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (ns com.seanshubin.clojure.tryme.concurrency)
- ;This sample demonstrates the benefits of pure functional code.
- ;In the method sortRecursiveParallel I can compute different parts of the sorting concurrently ;I can do this because I have no side effects, which gives me referential transparency, which means it does not matter ;which order I call my functions in. So I can place the instructions for each computation in a separate future without ;having to think about synchronization or locks ; ;A function is pure if ; it's inputs are explicit in the parameter list ; it's outputs are explicit in the return value, not side effects ; ;A function is not pure if ; reads the system clock ; reads or writes an environment variable ; reads or writes global variable ; reads or writes a file
- (defn sortRecursive [unsorted]
- (if (empty? unsorted) []
- (let
- [target (first unsorted)
- less (filter (fn [x] (< x target)) unsorted)
- greaterEqual (filter (fn [x] (>= x target)) unsorted)]
- (concat
- (sortRecursive less)
- [target]
- (sortRecursive (rest greaterEqual))))))
- (defn sortRecursiveParallel [unsorted]
- (if (empty? unsorted) []
- (let
- [target (first unsorted)
- less (filter (fn [x] (< x target)) unsorted)
- greaterEqual (filter (fn [x] (>= x target)) unsorted)
- sortedLess (future (sortRecursive less))
- sortedGreaterEqual (future (sortRecursive (rest greaterEqual)))]
- (concat
- (sortRecursive (deref sortedLess))
- [target]
- (sortRecursive (deref sortedGreaterEqual))))))
- (defn runSorts [unsorted]
- (let
- [sorted (sortRecursive unsorted)
- sortedParallel (sortRecursiveParallel unsorted)]
- [(str "unsorted = " unsorted)
- (str "sortRecursive = " (vec sorted)) ;convert to a vector so that we can realize the lazy sequence
- (str "sortRecursiveParallel = " (vec sortedParallel))]))
- ;code above is pure functional (inputs and outputs are explicit, no side effects) ; ;I like to clearly separate my pure functional code from other code ; ;code below is not pure functional (hidden inputs and outputs, side effects) ; (not done here) constructing a random without a seed talks to an external device (the system clock) ; random.shuffle mutates state (any time you get a random number you also update the seed) ; println talks to an external device (standard output)
- (defn shuffleUsingRandom [coll random] ;clojure does not have a built in shuffle that allows you to specify a random
- (let [arrayList (java.util.ArrayList. coll)]
- (java.util.Collections/shuffle arrayList random) ;side effect, the current seed for random changed
- (clojure.lang.RT/vector (.toArray arrayList))))
- (let [seed 12345
- random (new java.util.Random seed)
- numbers (range 1 21)
- shuffled (shuffleUsingRandom numbers random) ;side effect, shuffleUsingRandom is not pure
- results (runSorts shuffled)]
- (dorun (map println results))) ;using a first class function, but not pure functional because there is a side effect
- (shutdown-agents) ;clojure does not automatically shut down its futures when they are finished
- ;unsorted = [13 6 20 17 15 9 3 4 7 8 11 19 18 10 5 14 1 16 2 12]
- ;sortRecursive = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]
- ;sortRecursiveParallel = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]
Add Comment
Please, Sign In to add comment