Just some clojure notes:

default

 
; Left off pg 146 programming clojure
(ns user
  (:require [clojure.string :as str])
  (:require [clojure.set :as set])
  (:require clojure.repl))
;; Namespaces used in this file


(require 'clojure.java.io)
;; Require a library
;; Will return: nil if successful

;(find-doc "ns-")
;; Can be ran to find all documentation on
;; functions starting with ns- , for namespaces

(println)
(println "You gotta read and read and you gotta run and read")
(println)

;;;;;;;;;;;;;;;
;; leiningen ;;
;;;;;;;;;;;;;;;
(comment " 

lein repl
;; Start the clojure repl
;; leiningen must be installed

lein new app my-first-program
;; Start a new clojure project

lein run
;; Run your project

lein gooberjar
;; Build the project

java -jar target/gooberjar/clojure-goob-0.1.0-SNAPSHOT-standalone.jar
;; Run the project from java
;; This can be distributed

(System/exit 0)
;; Exit clojure repl in emacs

Ctrl+c  
Ctrl+d  
(quit)
(exit)
;; Will kill/quit the lein repl

*e
;; Special varaible that stores the last exception/error
;; Works in the repl

*1 *2 *3
;; Display the results of the last three evaluated expresions

(load-file "upload-all-info-to-brain.clj")
;; Loads a file into the repl

;end-leiningen-comments ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;
")

;;;;;;;;;;;
;; Cider ;;
;;;;;;;;;;;
(comment "

M-x cider-jack-in
;; This will start cider within emacs [done from inside the project folder]

C-c M-n
;; Switches cider repl from user namespace to namespace of current file

C-c C-k
M-x cider-load-buffer
;; Loads current file into cider repl

C-c C-q
;; Quit cider repl

;end-cider-comments ;;
;;;;;;;;;;;;;;;;;;;;;;
")

;;;;;;;;;;;;;
;; Clojure ;;
;;;;;;;;;;;;;

;; Look here is a comment from the ';' to the end of the line
;; Commas,,, are considered whitespace in clojure; they are optional

;; #_(someForm) Will ignore a form. Can be used to
;; easily comment out an area

;; Boolean wise: false and nil = false
;; 0 zero, () empty lists and everything else are all too True

;; _ can be used to ignore a binding
(let [[_ lion bird] ["head" "body" "wings"]]
  (println lion bird))
(println)

;; Instead of predicates ending in p like (sexyp :you) they end
;; in ? as in (sexy? :me)

(println "How come you put
the rest of me down here?\n")
;; Multiline string

(println '("Can't" "touch" "this"))
(println (quote ("Can't" "evaluate" "this")))
;; Code can be quoted to prevent evaluation
(println)

;; Built in functions ;;
;;--------------------;;
;; println - prints with a newline 
;; def - defines functions or data
;; defn - defines a function 
;; str - concatenates a list of arguments into a string 
;; conj - Conjoins a collection with an item

;; Reader Macros ;;
;;---------------;;
;; #(some-function) - Anonymous function
;; ;Blah blah - Comment
;; @(somFform => (deref someForm) - Deref
;; ^myMetaMan - Metadata
;; 'someForm => (quote someForm) - Quoting (prevents evaluation) 
;; #"stringToFind" - java.util.regex.Pattern
;; `x - Syntax quote
;; ~ - Unquote
;; ~@ - Unquote splicing
;; #'xyz => (var xyx) - var quote

(refer 'clojure.java.io)
;; Refers to the names in a library directly, without using full namespace path

(use 'clojure.java.io)
;; Will both require and refer a library

(use :reload 'clojure.java.io)
;(use :reload 'some.namespace.library)
;; You can reload updated code from a library already in use,
;; without restarting the repl

;(require '[clojure.string :as str])
;; Needed to run this file
;; Already added at top

;(doc str)
;; (doc name-of-some-function)
;; Doc will print documentation for a function

;(find-doc "abbrevi")
;; Will find any function with documentation matching a regular expression
;; This will match words containing "abbrevi" in the doc string, not just the
;; function name.


;(find-doc #"namespace\?$")
;(find-doc #"\?$")
;; Find all predicates that end in namespace?
;; Find all built in predicates in clojure. Predicates are functions that
;; will return either true or false. They are usually named with a ? at the
;; end. As in zero? In common lisp it would be zerop indicating a predicate.


;(source reverse)
;; (source some-function-name)
;; Will show the source of a function

;(pst)
;; Prints the stacktrace
;; Shows more information about exceptions from java stacktrace 

(println "Bye bye Pluto")
(println "Holas Planet-X")
(println)
;; Doh.. what's print do?

(def free-days 1)
(println free-days)
;; Create variable free-days with value of 1

(println (var free-days))
(println #'free-days)
;; Refer directly to a var; not it's value
;; #' is shothand version
(println)

(defn holas
  "Say hello to your fellow Nibiruians"
  [planet]
  (println
    (str "Holas " planet " all your babe are belong to me! dsh dsh dsh dsh")))
(holas "Nibiru")
;(doc holas)
;; Define a function
;; Call the function
;; Display documentation of your created function
;; When defining a function it will return with:
;; #'namespaceOfFuntion/functionName

(defn all-your-guy []
  (print "All your guy your guy guy guy all")
  (print " ")
  (println "your guy are belong to her! dsh dsh dsh dsh"))
(all-your-guy)
;(holas "Nibiru")
;(str *1 " " *2)
;; *1 *2 *3 Are special variables when working in the repl
;; They contain the results of evaluating the last three expressions
;; Note that if you are having trouble wrapping your head around this
;; Create a dummy function to run three times.
(println)

;(defn flood-special-variables [] "testing special vars")
;(flood-special-variables)
;(flood-special-variables)
;(flood-special-variables)
;(holas "Nibiru")
;(all-your-guy)
;(str *2 " " *1)
;*1
;*3
;; Dummy function to fill special variables *1 *2 *3
;; Run it 3x so they all contain the same data
;; Then run two other functions and play with the stars
;; This is best played with directly in repl,
;; Rather than running in file
;(println)

(defn flick-ear
  "Pick on little kid"
  ([] (flick-ear "twirp"))
  ([kids-name] (println (str "Pow! take that " kids-name "!"))))
(flick-ear)
(flick-ear "lil Joey")
;; Define a function with a default argument, if none given
;; Call default value, by giving no arguments
;; Entertain self at cost of little kid as argument 
(println)

(defn clan-member [clan-leader clan-deputy & clan-members]
  (println clan-leader "and" clan-deputy
  "rule over" (count clan-members) "clan members."))
(clan-member "Vjay" "Ariana" "Sejong" "Azazel")
;; Define a function that takes at least two arguments and any number more. 
;; This is done with & clan-members can contain any number of items
(println)

(println "Shh... Sh... She is casting a spell...")
(println (apply str (interleave "jasmine " "r o s e " "vanilla " "cinnamon")))
;; Cast an interwoven spell for some extra loving with your honey 
;; Don't know what it does... try (source interleave)
(println)

(println (str "Ok I'm going to send the letter right now. Hurry "
              "keep an eye on your mailbox!"))
(println (apply str (interleave "Hey can you read this?" "Yummy little monsters think
you taste better!" "So let the bed bugs feast away" "Please take off your
abracadabra :)")))
;; Precryptiontend
(println)

(println "There is no such thing as jibberish:")
(apply str (take-nth 4 "HYSPeuolym e mlacyesa tenl   ittythaotekul e eb r
eoemdfao fdnb  suyttgohesuir rssf ? ea"))
;; Depretendcryption
(println)

(println (.toLowerCase "DO YOU HATE ME BUSTING CAPS AT YOU?"))
;; Rid the world of uppercase letters
;; ** The . tells clojure to treat the function call as a java method
;; You can call java methods directly, this can be useful when clojure
;; does not have built in functions that java has.

(println (map #(Character/toUpperCase %) '(\u \f \o)))
;; Don't get rid of upper case characters... aliens will stop flying
;; Calling java method by Classname/staticMethod
;; Java interop
(println)

(println (clojure.string/upper-case "love is over!"))
;; Something zackySnacky may tattoo on your face... in all caps
(println)

(println (first '("mekel" "zale" "arjuna")))
;; Returns the first element of a list
(println)

(println (rest '("mekel" "zale" "arjuna")))
;; Returns a list without the first element
(println)

(println 
(cons "keyboard" '())
(cons "mouse" nil)
(cons "mouse" (cons "keyboard" nil))
)
;; Construct a list with cons

(println (list "one" "two" "three" "four"))
(println '(1 2 3 4))
;; Quoting lists, so they don't run
(println)

(println [:vector "hector" :hanibal-lector])
(print (nth [:vector "hector" :hanibal-lector] 2))
(println (last [:vector "hector" :hanibal-lector " in this sector"]))
;; Vectors are better than lists, when needing indexable sequences.
;; Lists have to go through the whole sequence one item at a time.
;; Vectors can jump to any index.
(println)

(println #{})
;; An empty set
(println)

;;---
(def englanish {"Don't stare at me" "No me mires fijamente",
                "Don't touch me" "No me toque",
                "You pig" "Cerdo",
                "Go to hell" "Vete al infierno"})
; Create a map from english to spanish
; The commas are optional

(println (englanish "Go to hell"))
;; Use the english map keys to get to spanish values 
;; Missing keys will return nil as value
;; Maps can be viewed as functions that return values when called with keys

(println (get englanish "Don't stare at me"))
(println (get englanish "Yippee ki yay" "Missing key, please add it"))
;; Get returns values from keys, can add default value for missing keys 
;;---
(println)

;;---
(def demons {:Baal "King of hell",
             :Agares "Teacher of languages",
             :Vassago "Teller of past and future",
             :Valefar "Tempter of thievery"})
;; Keywords can be used as keys in maps

(println (demons :Agares))
;; Return a value of a map by calling it with a keyword as the key

(println (:Vassago demons))
;; Pass a map to a keyword to get value of key
;;---
(println)

;;---
(defrecord heroe [name trait]) 
(->heroe "name" "trait")
(def first-hero (->heroe "Mekel" "Sniper"))
(def second-hero (->heroe "Vlado" "Thoughtcatcher"))
(def third-hero (->heroe "Katia" "Seducer"))
(println (:name first-hero))
(println (:trait first-hero))
;; Create a record
;; Instatiate the record
;; Create a record as if it was any other map
;; Return name of first-hero
;; Show me value of key that is a keyword :trait
;; Records are useful when a all the map's keys have someting in common

(heroe. "Mekel" "Sniper")
;; Another way to invoke your hero

#user.heroe{:name "Katia" :trait "Seducer"}
;; Another way to instantiate a hero
;;---
(println)

(println (string? "I am a marvelous string"))
(println (keyword? :my-colon-makes-me-a-keyword))
(println (symbol? '$&*#-you))
;; Predicates are named with a "?" at end and return true or false
;; Test for string, keyword, symbol
(println)

(defn grep-seducer [which-hero]
  (re-find #"Seducer" (:trait which-hero)))
;; Create a predicate function to check for certain trait
(println (grep-seducer third-hero))
(println (grep-seducer first-hero))
(println)

(defn four-letter-word? [word]
  (= (count word) 4))
;; Create a predicate function to test for thoughtcatchers
;; Test to see if second-hero is of thoughtcather race

(println
(filter four-letter-word?
  (str/split "quick dang luck tumble nook shot around"
  #"\W+"))
)
;; Create a filter to run a predicate function that
;; picks out all four letter words
(println)

(println
(filter (fn [vocab] (and
                    (> (count vocab) 6)
                    (not= vocab "beautiful")))
  (str/split "You are so beautiful and your eyes are so lovely...
  Yuck there is a cockroach!" #"\W+"))
)
;; What I feel about a guy hitting on me, when his vocabulary
;; contains only irrelevant words. 
;; And no, beautiful does not count!
;; Filters out words less than 6 characters long
;; Ignores beautiful and prints out any words passing the filter
;; (fn blah blah) - one way to create an anonymous function
;; #(blah blah) - another way to create an anonymous function

(println
(filter #(>= (count %) 0) (str/split "Ha ha
  I can say anything and get some!" #"\W+"))
)
;; The things I can say to any guy and get me some sexy
;; Example of using #() for an anonymous function
;;---
(println)

;---
(def glass-jar (atom #{}))
(swap! glass-jar conj "Pickle")
(println (deref glass-jar))
(println @glass-jar)
;; Define glass-jar with an empty atom map
;; Swap! glass-jar with a glass-jar conjoined with some pickles
;; Peek inside the glass-jar with deref
;; Peek inside glass-jar with @

(defn fill-glass-jar
  "Outputs message of items stuffed in glass-jar."
  [item-being-pickled]
  (swap! glass-jar conj item-being-pickled)
  (str item-being-pickled " stuffed in jar"))
;; Define a funtion to fill the glass-jar defined above

(fill-glass-jar "Onion")
(fill-glass-jar "Carrot")
;; Stuffs some items in the glass-jar

(println @glass-jar)
;; Peek in the glass-jar to see if anything is yummy.
;;---
(println)

(println (string? "I am a marvelous string"))
(println (keyword? :my-colon-makes-me-a-keyword))
(println (symbol? '$&*#-you))
;; Predicates are named with a "?" at end and return true or false
;; Test for string, keyword, symbol
(println)

(defn summarize-boring [sentence]
  (let [[fword sword tword] (str/split sentence #"\s+")]
  (str/join " " [fword sword tword "blah blah"])))
(println (summarize-boring "Is your dad a thief? Cause I saw him
  steal all the stars out of the sky and put them in
  your eyes."))
;; Use let for lexical bindings, local to this function only 
(println)

(println (resolve 'holas))
;; Show fullname of binding, namespace/name
;; Must exist in current namespace
(println)

;;---

(in-ns 'fakespace)
;; Switch to a new namespace, creating it if non-existant

(def faker "I fake you")
;; Create var in namespace: fakespace 

(clojure.core/use 'clojure.core)
;; Pull clojure.core into current namespce
;; So builtin clojure functions will work

(println faker)
;; Print faker while in fakespace

(in-ns 'user)
;; Switch back to user namespace

(println (str fakespace/faker " user namespace"))
;; Print faker from fakespace while in user namespace

;;---
(println)

(import '(java.io InputStream File))
(println (.exists (File. "/home")))
;; Import a java class
;; Use something in the java class
(println)

(apropos "rand")
;; Clojure 1.3 and later has apropos
;; Can be used to find functions with rand in name

;;---
(println 
(defn double-swing
  "Take two swings with rand dmg 0..9"
  []
  (take 2 (repeatedly #(rand-int 10))))
)
;; Create function that swings two random numbers

(let [swings (double-swing)]
  (println swings)
  (println "You swing for:" (first swings) "dmg")
  (println "You swing again for:" (second swings) "dmg"))
;; Swing some random numbers
;; let keeps bindings local/lexical to itself
;;---
(println)

(println
(def java-random (new java.util.Random))
)
(println (. java-random nextInt))
(println (. java-random nextInt 10))
;; Create a random number generating function
;; from by duplicating the java one
;; Test out a random number with nextInt
;; Generate random number from 0-10

(println
(defn two-handed-swing
  "Take a swing with a two handed weapon dmg 0..29"
  []
  (. java-random nextInt 30))
)
;; Create function to swing a two handed weapon
;; with 0 to 29 damage

(let [swing (two-handed-swing)]
  (println swing)
  (println "You swing for:" swing "dmg"))
;; Let out a swing:
;; By the power of javaskull... I have the power!
(println)

;;---
;(javadoc java.util.Locale)
;; Open a browser with documentation on Locale
;; java.util.Locale 

(import '(java.util Locale))
(println (java.util.Locale/KOREA))
(println (. Locale KOREAN))
;; Import a java class
;; Get locale for country
;; Get locale for language 
;;---
(println)

;;---
(def yves {:name "yves" :hp 30 :str 10 :dex 12 :lck 14})
(def ada {:name "ada" :hp 9 :str 8 :dex 18 :lck 6})
;; Create player yves

(println
(defn is-whimpy? [player]
  (if (<= (player :hp) 10)
  (do
    (println "Attack!" (player :name) "is a whimp!")
    true)
  (do
    (println "Careful..." (player :name) "is not a whimp.")
   nil)))
)
;; Create a function to find whimps
;; Less than 10 health is a whimp
;; Pushing out side effects with do
;; Returning only last return value, anything else
;; will be from a side effect.

(is-whimpy? yves)
(is-whimpy? ada)
;; Is you whimpy?
;;---
(println)

(println (every? is-whimpy? [yves ada]))
;; Use every? with a predicate to test if all are agreeable

(println (some is-whimpy? [ada yves]))
;; Check if some are whimps
(println)

(println (not-every? is-whimpy? [yves ada]))
;; Make sure not all are whimps

(println (not-any? is-whimpy? [ada yves]))
;; See if none are whimpy
(println)

(println
(take 2 (for [enemy [yves ada] :when (is-whimpy? enemy)] (:name enemy)))
)
;; Choose only whimpy enemies

(for [enemy [yves ada] :while (not (is-whimpy? enemy))]
  (println (:name enemy) (:hp enemy)))
;; List enemies name and hp, who are not whimps 

(println
(loop [failed-marriages [] x 0]
  (if (<= 11 x)
    failed-marriages
    (recur (conj failed-marriages x) (inc x))))
)
;; Count up your failed marriages
(println)

(println
(vec (rest (range 22))) "\n"
(into [] (take 18 (iterate inc 0))) "\n"
(into [] (drop-last (range 20))) "\n"
)
;; Look mommy I can count!

(println #{:obsessive :compulsive :disorder})
(println (sorted-set :obsessive :compulsive :disorder))
;; Sets do not have reliable order 
;; Use sorted when order matters

(println {:kitties "prr" :puppies "grr"})
(println (sorted-map :puppy "bark" :kitty "mwaowr"))
;; Maps do not have reliable order 
;; Sort your order maps out by key

(println (conj '(:mouse :cheese) :peanut-butter))
;; conj adds item to front of list

(println (conj [:chair :table :food] :fork))
;; conj adds to end of vector

(println (into '(:bucket :cup :shovel) '("sand" "rock" "pebble")))
;; into adds to front of a list

(println (into [:apple :acorn] ["worm" "squirrel"]))
;; into adds to end of vector
(println)

(println (range 20))
;; Create a sequence of 20 items with range

(println (range 0 12))
;; Start a zero and generate 12 numbers

(println (range 0 61 5))
;; Count by 5 from 0 to 60 

(println (repeat 10 2))
(println (repeat 5 "y"))
;; Return ten two's
;; Return five y's

(println (take 6 (iterate inc 12)))
;; Lazy sequence with take and iterate
;; Iterate is infinite

(println (take 20 (cycle (range 2))))
;; Cycle through some binary
(println)

(println (interpose "+" ["drugs" "sex"]))
(println (apply str (interpose " + " ["drugs" "sex"])))
;; Choose character to seperate items in a sequence
;; Apply str more smoothly 

(use '[clojure.string :only (join)])
(println (join \+ ["Boredom" "Curiosity"]))
;; Use join instead of interpose
(println)

(println (set [4 5 6 7]))
;; Create a set

(println (hash-set 5 6 7 8))
;; Create a set with hash-set

(println (vec (range 8)))
;; Create a vector 0..7

(println (take 20 (filter odd? (iterate inc 1))))
;; Filter takes a predicate and a collection

(println (split-at 12 (range 20)))
;; Split a collection at chosen spot

(println (split-with #(>= % 20) (range 43 0 -3)))
;; Split odd numbers over 20 from ones less than 20

(println (drop-while #(>= % 20) (range 43 0 -3)))
;; Drop numbers over a range

(println (drop-while #(<= % 120) (range 0 200 15)))
;; Get rid of anything under 121
(println)

(println (map #(format "%s lick slrp," %) ["cat" "dog" "gator"]))
;; Transform each item in vector with map

(println (reduce + '(2 5 9)))
;; Reduce sequence by adding each to the  next 

(println (reduce * (range 5 25 5)))
;; Reduce by multiply seq

(println (sort [23 5 42]))
;; Sort some numbers

(println (sort-by #(.toString %) [23 5 42]))
;; Sort numbers as if they are strings

(println (sort > [23 5 42]))
;; Sort top to bottom

(sort-by :rank < [{:rank 5} {:rank 3} {:rank 1}])
;; Sort by rank lowest to highest
(println)

(println
(for [item ["sword" "belt" "hat"]]
  (format "I have a %s" item))
)
;; List items with a for
(println)

(println (re-seq #"\w+" "create me a sequence"))
;; Create a sequence of words from a sentence 

(println (sort (re-seq #"\w+" "please do not reorder me")))
;; Sort a seq of words from a sentence

(println (drop 3 (re-seq #"\w+" "I will not have sex with you")))
;; Drop some words for some fun

(println (map #(.toUpperCase %) (re-seq #"\w+" "Nope, not again")))
;; Capitalize words pulled into a seq
(println)

(println (map #(.getName %) (.listFiles (File. "."))))
;; List names of files in current directory
;; using java's java.io
;; Already imported java.io earlier in file

(println (count (file-seq (File. "."))))
;; Count all files in current folder and sub-directories

;(take 4 (line-seq (reader "project.clj")))
;; Show the first 4 lines of a file

#_(println (with-open [read-file (reader "project.clj")]
  (count (filter #(re-find #"\S" %) (line-seq read-file)))))
;; Count non blank lines in a file
;; Use with-open to make sure they are closed
(println)

(println (peek '(1 2 3)))
;; Return first element in a list
;; Return last item in vector
;; More efficient that last

(println (pop '(1 2 3)))
;; Return a new list without first item
;; Return new vector witout last item
;; pop errors on empty seq
(println)

(println (get [:ugly :fun :pretty] 1))
;; Get value at index
;; Return nil if index off the chart

(println ([:sexy :handsome :funny] 0))
;; Vector are functions too

(println (assoc [:weird :cool :popular] 2 :smart))
;; Return a new vector with index value swapped in 
(println) 

(println (take 2 (drop 1 [:steak :potato :eggs :bacon])))
(println (subvec [:steak :potato :eggs :bacon] 2))
(println (subvec [:steak :potato :eggs :bacon] 0 3))
;; Get a subset of a vector
;; Subvec is faster than take and drop on vectors
(println)

(println (keys {:tooth "ache" :ear "ring" :eye "contact"}))
;; Return all keys of map

(println (vals {:tooth "ache" :ear "ring" :eye "contact"}))
;; Return all values from map

(println ({:tooth "ache" :ear "ring" :eye "contact"} :eye))
(println (:ear {:tooth "ache" :ear "ring" :eye "contact"}))
;; Return value of key
(println)

(println
(def nasties {:nose "booger" :ear "wax" :booboo "poopoo"})
)
(println (nasties :nose))
(println (contains? nasties :nose))
(println (get nasties :ear "Sorry not found!"))
(println (get nasties :hand "Sorry not found!"))
;; Return map key values
;; Return a default value instead of nil
(println)

(println
(def wizard {:level 1,
             :BAB 0,
             :FS 0
             :RS 0
             :WS 0})
)
;; Create a wiz map to play with

(println (assoc wizard :special "Summon Familiar"))
;; Add to map with assoc

(println (dissoc wizard :level))
;; Remove from map with dissoc

(println (merge wizard {:school "Necromancy" :familiar "Hawk"}))
;; Merge a map with wizard map
(println)

(println
(merge-with
  concat
  {:day ["Rooster"] :night ["Owl"]}
  {:day ["Squirrel"] :night ["opossum"]}
  {:day ["horse"] :night ["wolf"]})
)
;; Merge values with similar keys to same key
(println)

(println
(def small-bosses #{"Pink Dragon" "Blue Dragon" "Pixie" "Golem"})
(def challengers #{"Ariana" "Ariadnai" "Saida" "Golem"})
)
;; Create set of small-bosses
;; Create set of challengers

(println (set/union small-bosses challengers))
;; clojure.set already required as set, above in file 
;; Returns all elements in a new set
;; Throw everyone in an arena

(println (set/intersection challengers small-bosses))
;; Return elements that are in both sets

(println (set/difference small-bosses challengers))
;; Find elements in small-bosses that are not
;; in challengers

(println (set/difference challengers small-bosses))
;; Find elements in challengers that are not
;; in small-bosses

(println (set/select #(< (.length %) 6) (set/union small-bosses challengers)))
;; Find elements greater than six characters
;; in the union of small-bosses and challengers
(println)

(println
(def clans
  #{{:clan-name "Rejects" :leader "Mekel"}
    {:clan-name "Breakfast Clubbers" :leader "Taizya"}
    {:clan-name "Rats Nest" :leader "Gauss"}
    {:clan-name "Pickled Kittens" :leader "Kasha"}})
(def clannies
  #{{:name "Taizya" :hp 220 :location "Dog House"}
    {:name "Monroe" :hp 300 :location "Hideout"}
    {:name "Engelbart" :hp 190 :location "Backyard"}})
(def mobs
  #{{:mob-name "Pink Dragon" :mob-hp 2200 :location "Dog House"}
    {:mob-name "Blue Dragon" :mob-hp 2800 :location "Toy Box"}
    {:mob-name "Pixie" :mob-hp 4400 :location "Backyard"}})
;; Creates some sequences to play with
)

(println (set/rename mobs {:hp :health}))
;; Return a set with :hp keys replaced with :health

(println (set/select #(> (:hp %) 200) clannies))
;; Select a set with clannies that have hp over 200 

(println (set/project mobs [:name]))
;; Project the names of all mobs

(for [m mobs c clannies] (concat m c))
;; Return all possible row combinations between
;; mobs and clannies

(println (set/join mobs clannies))
;; Join clannies and mobs that are in same
;; location into a set
(println)

(println (set/join clannies clans {:leader :name}))
;; Join clannies and clans by mapping
;; with keys that do not exist 
(println)

(println
(set/project
  (set/join
    (set/select #(= (:location %) "Dog House") mobs)
      clannies) [:name])
)
;; Return all clannies that match the same location
;; as Dog House from mobs
(println)

(println
(defn fibo [n]
  (letfn [(fib
            [current next n]
            (if(zero? n)
              current
              (recur next (+ current next) (dec n))))]
    (fib 0N 1N n)))
)
;; Use recur in order not to use up stack
;; Create a Fibonacci function

(println (fibo 1000))
;; Try out fibo function
(println)

(println
(defn fibozy
        ([]
         (concat [0 1] (fibozy 0N 1N)))
        ([a b]
         (let [n (+ a b)]
           (lazy-seq
            (cons n (fibozy b n))))))
)
;; Create a lazy version of fibonacci
;; with lazy-seq

(println (take 15 (fibozy)))
;; Use lazy fibo function with take
;; To list out fibo numbers
(println)

(println
(defn cg-fibo []
  (map first (iterate (fn [[a b]] [b (+ a b)]) [0N 1N])))
)
;; Use map to create some fibo func.
;; Fibonacci numbers are infinte by grabbing
;; lazily you can get at numbers without eating
;; too much resources.
;; It is better to create a function that creates
;; a sequence, than it is to define a variable
;; of some sort, as the variable will eat up
;; memory without being garabge collected

(println (take 16 (cg-fibo)))
;; Use map cg-fibo with take

(println
(def pretty-little-fibber (take 80000 (cg-fibo)))
)
;; Doesn't return any fibs until needed
;; A lazy litter fibber
;; Useful on repl so it does not get to greedy

;(set! *print-length* 10)
;; You can set the repl to only return the first
;; 10 items of a lazy seq

(println (nth pretty-little-fibber 202))
;; Only grab the 202nd fib she told
;; Without worrying about the previous fibs
;; you could of heard
(println)

(println)
;;;;;;;;;;;;;;;;;;;;;;;;
;; Use external files ;;
;;;;;;;;;;;;;;;;;;;;;;;;

#_(
(use '[clojure.xml :only (parse)])
(parse (java.io.File. "characters.xml"))
(println
(for [x (xml-seq
         (parse (java.io.File. "characters.xml"))) ;
     :when (= :character (:tag x))]
  (:name (:attrs x)))
)
;; Read xml file
)


;;;;;;;;;;;;;;;;
;; Vocabulary ;;
;;;;;;;;;;;;;;;;
(comment "

higher order function - function that takes functions as arguments and/or
                        returns functions as results.

homoiconic - code is data

")
;;end-vocabulary-comment ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;

default