Last active
April 26, 2017 13:20
-
-
Save peat/5951497 to your computer and use it in GitHub Desktop.
Fun with Clojure and Futures.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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