Skip to content

Instantly share code, notes, and snippets.

@peat
Last active April 26, 2017 13:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peat/5951497 to your computer and use it in GitHub Desktop.
Save peat/5951497 to your computer and use it in GitHub Desktop.
Fun with Clojure and Futures.
; To run these examples (assuming you have homebrew installed):
;
; $ brew install leiningen
; ...
; $ lein repl
;
; ... this drops you into the Clojure REPL (Read, Evaluate, Print, Loop).
;
; Copy and paste the lines below and play around.
(def names ["Alice" "Bob" "Clarice" "Dave"])
; creates a vector (a fancy list) of strings called "names"
(first names)
; returns the first value in the "names" vector; you'll see it printed out in the
; REPL (it prints out the values returned by the instructions you give it)
(nth names 0)
; find the 'nth' value at index 0 in names -- like names[0] in ruby, or $names[0] in PHP.
(str "Hello, " (nth names 2))
; returns the string "hello " concatenated with the third name: "Hello, Clarice"
(defn hello [n] (str "Hello, " n))
; creates a new function named 'hello' which takes one argument 'n'
(hello (nth names 2))
; does the same thing as line 21! Yay, functions.
(map hello names)
; Whoa. Cool stuff: runs the 'hello' function against every value in 'names', and
; returns the result as a list. Beats the pants off of a 'for' loop!
(defn long-hello [n] (Thread/sleep 5000) (hello n))
; Defines a function that sleeps for 5 seconds, then runs our 'hello' function.
; Pretend this is going to the database, or some other long running process.
(long-hello "Joe")
; Execute the 'long-hello' function. See it in action! notice that your REPL is blocked
; for input ... this represents your program freezing while it's trying to do something else.
; Gross.
(map long-hello names)
; OMG, SO GROSS. We had to wait 20 seconds for all of our names to get hello'd, even
; though this is a task that could be done in parallel! There's a better way. Several, in fact.
; For this example, we'll use "futures"
(defn future-hello [n] (future (long-hello n)))
; Lets wrap 'long-hello' in a 'future'. A "future" will run 'long-hello' into a separate thread,
; then cache the result so that we can access it later. The important part is that your program
; (or REPL) can continue running.
(map future-hello names)
; Whoa, instantaneous results ... but WTF? The values haven't been calculated yet, so we
; have a list of futures that are executing. Hmm.
(def my-futures (map future-hello names))
; Lets stick all those futures into a value that we can examine ... in the future!
; Now we want to get the results from those futures ...
(map deref my-futures)
; So we run the "deref" function on those futures. "deref" is just a fancy way to say
; "wait until we can pull a result from a future, and return that result."
; ... because all of our futures are delayed 5 seconds, and they're running in parallel, this
; will return a list of greetings 5 seconds after we created "my-futures" ... cool!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment