Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Browse files

It's all data

  • Loading branch information...
commit cc67caed0529d49347a7db6ce5591d35d5967ceb 1 parent da5e46c
@stuarthalloway stuarthalloway authored
Showing with 235,039 additions and 11 deletions.
  1. +234,936 −0 data/words
  2. +2 −2 script/console
  3. +2 −7 script/swank
  4. +99 −2 src/labs/its_all_data.clj
234,936 data/words
234,936 additions, 0 deletions not shown
4 script/console
@@ -1,8 +1,8 @@
for f in lib/*.jar; do
-java -cp $CLASSPATH jline.ConsoleRunner clojure.main -e "(use '[clojure.contrib def duck-streams ns-utils pprint repl-utils shell-out]) (require '[clojure.contrib.str-utils2 :as s])(require 'labrepl) (labrepl/-main)" -r
+java -Xmx1GB -cp $CLASSPATH jline.ConsoleRunner clojure.main -e "(use '[ :only (spit read-lines reader writer)] '[clojure.contrib def ns-utils pprint repl-utils shell-out]) (require '[clojure.contrib.str-utils2 :as s])(require 'labrepl) (labrepl/-main)$LABREPL_SWANK" -r
9 script/swank
@@ -1,8 +1,3 @@
-for f in lib/*.jar; do
-java -cp $CLASSPATH clojure.main -e "(use '[clojure.contrib def duck-streams ns-utils pprint repl-utils shell-out]) (require '[clojure.contrib.str-utils2 :as s]) (require 'swank.swank) (swank.swank/start-repl 4005)" -r
+export LABREPL_SWANK="(require 'swank.swank) (swank.swank/start-repl 4005)"
101 src/labs/its_all_data.clj
@@ -68,10 +68,107 @@
(code (:first-name me))]
[:li "Keywords are also used to name options. So, you can use only the " (c primes) " function from the lazy-seqs lib:"
(code (use '[clojure.contrib.lazy-seqs :only (primes)]))]
- [:li "Now that we have the primes loaded, we might as well look at a few of them. We will cover " (c for) " in detail later, but for now use the " (c :while) " keywoard option to retrieve only those primes less than a thousand:"
+ [:li "Now that we have the primes loaded, we might as well look at a few of them. We will cover " (c for) " in detail later, but for now here is how to use the " (c :while) " keyword option to retrieve only those primes less than a thousand:"
(code (for [p primes :while (< p 1000)] p))]]])
+(defn collections
+ []
+ [[:h3 "Collections"]
+ [:ol
+ [:li "Lists are the traditional lisp linked list. You can created them with " (c list) " or with a quoted literal:"
+ (code (list 1 2 3))
+ (code '(1 2 3))]
+ [:li "List support efficient insertion at the front via " (c cons) ", which is short for \"construct\"."
+ (code (cons 0 '(1 2 3)))]
+ [:li "Vectors are indexed by integer, and can be created with a literal form in sqaure brackets:"
+ (code ["hello" "world"])
+ (code (get ["hello" "world"] 1))]
+ [:li "Map literals are enclosed in " (c {}), "."
+ (code "{:country \"US\" :capitol \"Washington, D.C.\"}")]
+ [:li "Commas are whitespace. You may prefer using them to delimit pairs in map literals:"
+ (code {:country "US", :capitol "Washington, D.C."})]
+ [:li "Character literals look like " (c \Z) ", and sets are delimited by " (code #{}), ", so the set of English vowels is "
+ (code #{\a \e \i \o \u})]
+ [:li "Vectors, maps, and sets are all associative collections. You can use them as functions to lookup values:"
+ (code (["hello" "world"] 1))
+ (code ({:country "US", :capitol "Washington, D.C."} :country))
+ (code (#{\a \e \i \o \u} \z))]
+ [:li "Write a function " (c vowel) " that returns its input if it is a vowel, or " (c nil) " otherwise."
+ (code (defn vowel [ch] (#{\a \e \i \o \u} ch)))]
+ [:li "Since the set of vowels is already a function, you could write " (c vowel) " more concisely as "
+ (code (def vowel #{\a \e \i \o \u}))
+ "Use the REPL to test that the two versions of " (c vowel) " are equivalent."]]])
+(defn seqs
+ []
+ [[:h3 "Seqs"]
+ [:p "A sequence (seq) is a logical list. All Clojure collections are seq-able, that is, they can be treated as seqs. Using the sequence library, you can program in a general way against any Clojure collection type. Here are just a few examples:"
+ [:ol
+ [:li "You can get the " (c first) " or " (c rest) " of any collection:"
+ (code (first [1 2 3]))
+ (code (rest [1 2 3]))
+ "Try taking the " (c first) " and " (c rest) " of some maps and sets. What are the return types?"]
+ [:li "You can " (c take) " or " (c drop) "n elements of a collection."
+ (code (take 5 (range 100)))
+ (code (drop 5 (range 100)))
+ "Again, try these functions against some other collection types as well."]
+ [:li "You can " (c map) " a function acorss the elements of a collection, applying the function to each:"
+ (code (map (fn [x] (* x 2)) (range 50)))]
+ [:li "You can " (c filter) " a collection, returning only those elements that match a predicate:"
+ (code (filter odd? (range 50)))]
+ [:li (c reduce) " walks a collection, applying a function to pair and carrying the result. The following are equivalent:"
+ (code "(reduce + [1 2]) => (+ 1 2)")
+ (code "(reduce + [1 2 3]) => (+ (+ 1 2) 3)")]
+ [:li "Try reducing something a little bigger."
+ (code (reduce + (range 101)))]
+ [:li "Because all collections can be treated as sequences, it is very easy to extend Clojure's power. If you write a function that works with seqs, all data can use it. The hardest part of writing Clojure apps is often deciding if the function you want already exists. What if you wanted something like " (c reduce), ", but returning all ther intermediate steps. No problem, that is called " (c reductions) ": "
+ (code (use '[clojure.contrib.seq-utils :only (reductions)])
+ (reductions + (range 101)))]]]])
+(defn a-little-real-data
+ []
+ [[:h3 "A Little Real Data"]
+ [:p "The file " (c data/words) " contains a typical Unix words file. Let's see how easy it is to analyze data using Clojure."]
+ [:ol
+ [:li "Use " (c read-lines) " to load the words file into a variable named " (c words) ". "
+ (code (def words (read-lines "data/words")))]
+ [:li "Use " (c count) " to verify that you got the words."
+ (code (count words))]
+ [:li "What is your favorite English word containing the string \"root\"? Use filter to get the possible choices:"
+ (code "(filter #(.contains % \"root\") words)")]
+ [:li "How many words in the file start with A?"
+ (code "(count (filter #(.startsWith % \"A\") words))")]
+ [:li "Let's generalize that a bit. The " (c frequencies) " function returns a map of values to the number of times each value occurs. Build a frequencies table by initial letter"
+ (code (use '[clojure.contrib.seq-utils :only (frequencies)])
+ (frequencies (map first words)))
+ "(Note that hear you see one advantage of working with all the data, instead of thinking up a few examples. The results demonstrate that we need to decide how to deal with upper vs. lower case letters."]
+ [:li "How about a frequency distribution by the length of the word?"
+ (code "(frequencies (map #(.length %) words))")]
+ [:li "Frequencies are easier to visualize with a bar chart. Load the incanter charting library:"
+ (code (use 'incanter.chart))]
+ [:li "The " (c bar-chart) " function expects a sequence of categories, followed by a sequene of values. Use " (c let) " to capture frequencies in a local variable, and then call " (c keys) " and " (c values) " to pass the data to " (c bar-chart) ". "
+ (code (let [f (frequencies (map first words))]
+ (view (bar-chart (keys f) (vals f)))))]]])
+(defn bonus
+ []
+ [[:h3 "Bonus"]
+ [:ol
+ [:li (c bar-chart) " takes addional options for controlling the display of the chart. Use them to make the frequencies chart more appealing."]
+ [:li "Our first " (c reduce) " example showed using reduce to perform repeated addition. But in Clojure, the " (c +) " function can itself perform repeated addition! What advantages does " (c reduce) " offer over implicit reduction within a funtion?"]
+ [:li "Implement your own version of " (c frequencies) " using " (c reduce) "."]
+ [:li "Pick a language that you know well. What feature of your chosen language is analogous to Clojure keywords? To Clojure symbols? What do the differences (if any) imply?"]
+ [:li "The " (c reverse) " function returns the reverse of a collection."
+ (code (reverse [1 2 3]))
+ "Its behavior with strings may surprise you, but it is consistent:"
+ (code (reverse "foobar"))
+ "Why is " (c reverse) "'s behavior the right thing to do, even for strings, and what options can/should be provided for String->String functions?"]]])
(defn instructions
(concat (some-data-types)
- (name-types)))
+ (name-types)
+ (collections)
+ (seqs)
+ (a-little-real-data)
+ (bonus)))

0 comments on commit cc67cae

Please sign in to comment.
Something went wrong with that request. Please try again.