Instantly share code, notes, and snippets.

Embed
What would you like to do?

Functional programming isn't scary: Notes

About Clojure

Websites

Videos by Rich Hickey (creator of Clojure and designer of Datomic)

About the Cape Town Clojure User Group

Come join us at Codebridge on the 18th of May for our next user group meeting! Follow our Twitter account to stay informed.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; FUNCTIONAL COMPOSITION DEMO ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; define a vector [] of maps {key value} at the symbol 'the-watch'
(def the-watch
[{:name "Samuel Vimes" :species "Human" :rank "Commander"}
{:name "Carrot Ironfoundersson" :species "Human, Dwarf (honorary)" :rank "Captain"}
{:name "Fred Colon" :species "Human" :rank "Sergeant"}
{:name "C. W. St J. (Nobby) Nobbs" :species "Human (licensed)" :rank "Lance-Corporal"}
{:name "Angua von Überwald" :species "Werewolf" :rank "Lance-Corporal"}
{:name "Detritus" :species "Troll" :rank "Lance-Corporal"}])
;; all expressions return a value. this one, a call to the 'count'
;; function, returns the count of the elemnts in 'the-watch'.
(count the-watch)
;;
;; defines a function at the symbol 'has-species? with two arguments.
(defn has-species?
[species character]
;; re-find matches regular expressions to strings.
(re-find species
;; keywords are also functions when given a map!
;; will return the value at ':species' key.
(:species character)))
;; partial composes a function with an argument 'baked' in.
;; gives us a new function to use directly.
;; regular expressions are written as strings with a # prefix.
(def human? (partial has-species? #"Human"))
;; filter composes a predicate - a true/false function - with a
;; collection. returns only those which match the predicate.
(filter human? the-watch)
;;
;; compose a string representation of a character
(defn stringify
[character]
(str (:rank character) " "
(:name character) ", "
(:species character)))
;; run each character through the stringify function
(map stringify the-watch)
;;
(comment
;; putting it all together to do something meaninful:
;; println - our first 'impure' function!
(println (clojure.string/join "\n"
(concat (list "The Watch:"
"-----------------------")
(map stringify the-watch))))
;;
;; make it readable by using '->>', a 'threading' macro, which
;; reorganises code during compilation.
;; semantically identical to the previous version.
(->> the-watch
(map stringify)
(concat (list "The Ankh-Morpork Watch:"
"-----------------------"))
(clojure.string/join "\n")
(println))
;;
;; filter non-humans!
(->> the-watch
;; complement makes a function that returns the opposite boolean
;; value to the function it is passed
(filter (complement human?))
(map stringify)
(concat (list "The Ankh-Morpork Watch:"
"-----------------------"))
(clojure.string/join "\n")
(println))
;;
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; IMMUTABLE DATA DEMO ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def a "this is a")
(println a)
;;
;; bind [1 2 3] to 'a' for the duration of this let form's contents
(let [a [1 2 3]]
(println a)
;; rebind a
(let [a [4 5 6]]
(println a))
(println a))
;;
(println a)
;;
;; an example that actually does something:
(let [content (slurp "/Users/robert/quote.edn")]
(println content)
(let [content (read-string content)]
(println (str "\n\t'" (:quote content) "' - " (:author content) "\n")))
(println content))
;;
(println content)
;;
{:quote "Always be wary of any helpful item that weighs less than its operating manual."
:author "Terry Pratchett"}
this file left intentionally blank, because Gist doesn't have a delete-file function!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment