The Curious Case of Clojure’s (case)

May 14th, 2011

Clojure has a (case) macro which cost me a little time last night because I didn’t read the documentation carefully enough. Consider this REPL session:

user=> (def x 1)
#'user/x
user=> (def y 2)
#'user/y
user=> (case 1,   x "GOT x",    y "GOT y",    "NOTHIN'")
"NOTHIN'"
user=> (case x,   x "GOT x",    y "GOT y",    "NOTHIN'")
"NOTHIN'"

That seems a little odd. Two “constants” used as test expressions, but unexpected results. How about this:

user=> (case 'x,    x "GOT x",    y "GOT y",   "NOTHIN'")
"GOT x"

Interesting. It’s almost like (case) doesn’t evaluate the test expressions. I’ll read the docs a little closer:

The test-constants are not evaluated. They must be compile-time
literals, and need not be quoted. If the expression is equal to a …

Ah. Mystery solved. x and y in my case are treated as raw symbols! For me, this is a surprisingly un-dynamic behavior for Clojure. I understand it’s for constant-time dispatch, but still.

For what it’s worth, the real example where this came up makes it less obvious:

(case result
   JFileChooser/APPROVE_OPTION   ...
   JFileChooser/CANCEL_OPTION    ...
   ...)

Maybe this will help someone else be less dense than me. The correct solution, I think, is to use condp or cond:

user=> (condp = 1,    x "GOT X",    y "GOT Y",   "NOTHIN")
"GOT X"

Cheers.

clojure

Java Concurrency Pitfalls (in Scala) Answers

May 10th, 2011

Recently, Cay Horstmann posted a dozen Java concurrency pitfalls ported to Scala for extra pitfalliness. I had fun figuring them out. Here’s what I came up with.

I won’t copy all the code here, just provide my answers.

  1. The var stop isn’t synchronized in any way (synchronized, AtomicBoolean, etc) so there’s a chance that when it’s set to false, the change won’t be seen in the thread.
  2. Here, stop is an AtomicBoolean, fixing the issue in problem #1. That’s good. However, if doSomething() throws an exception done.put("DONE") will never execute and done.take() will wait forever.
  3. Here, Thread.run() is called rather than Thread.start(). The so-called “BackgroundTask” will actually run in the “foreground”
  4. ConcurrentHashMap.keySet().toArray will give a “weakly consistent” snapshot of the keyset at the time of the call. By the time it returns, the keys in the map may have changed completely.
  5. Oops. A string literal is used for the lock meaning that all instances of Stack will most likely share the same lock.
  6. Oops. A new “lock” is created every time push() is called, which is just as good as no lock.
  7. Here values is mercifully synchronized, but the var size isn’t. That is, if size is used in any other methods it may not be synchronized correctly.
  8. A do/while is used for the condition variable rather than just while. If cond is in a signaled state initially, the condition that size is zero may not be checked.
  9. If out.close() throws an exception, the myLock.unlock() will not be executed.
  10. Here, a string is being added to a blocking queue within a UI event handler. If the queue is full, queue.put() will block causing the UI to become unresponsive.
  11. I’m not totally sure with this one. I can think of a few things that could go wrong. First, if a listener is added or removed while fireListeners() is executing, you could get a ConcurrentModificationException. I think so anyway. I wasn’t able to find any indication of how ArrayBuffer iteration handles this. Second, since the listeners are notified with the lock held, you’ll almost certainly get a deadlock eventually, usually a lock inversion with some other thread that’s calling SwingUtilities.invokeAndWait().
  12. Ridiculously, SimpleDateFormat is NOT THREADSAFE! So using the same formatter from multiple threads is a recipe for sadness.

I wonder what I missed.

Cheers!

java, scala, software engineering, Uncategorized , ,

20 Minute File Explorer with Seesaw

April 30th, 2011

Seesaw, my Clojure/Swing experiment has been making a lot of progress. Earlier today I added basic support for JTree which is kind of the last major Swing component that had no support in Seesaw. As an test, I thought I’d try making a file explorer with the directory tree on the left and file list on the right. It took about 20 minutes and was way less tedious than the equivalent raw Swing code you’d write in Java or Clojure.

The full code for the example can be found on github.

Here’s what it ended up looking like:

Code Highlights

There are three code highlights.

Set up a model for the tree using the same pattern as (cloure.core/tree-seq):

; Make a model for the directory tree
(def tree-model
  (simple-tree-model
    #(.isDirectory %)
    (fn [f] (filter #(.isDirectory %) (.listFiles f)))
    (File. ".")))

Set up the structure of the frame. I think this reads pretty nicely:

  (frame :title "File Explorer" :width 500 :height 500 :pack? false :content
    (border-panel :border 5 :hgap 5 :vgap 5
      :north (label :id :current-dir :text "Location")

      :center (left-right-split
                (scrollable (tree :id :tree :model tree-model :renderer render-file-item))
                (scrollable (listbox :id :list :renderer render-file-item)))

      :south (label :id :status :text "Ready")))

Set up selection event handling:

  (listen (select [:#tree]) :selection
    (fn [e]
      (if-let [dir (-> (selection e) first last)]
        (let [files (.listFiles dir)]
          (config (select [:#current-dir]) :text (.getAbsolutePath dir))
          (config (select [:#status]) :text (format "Ready (%d items)" (count files)))
          (config (select [:#list]) :model files))))))

Here, the widgets are being retrieved by id with the (select) function. Alternatively, I could have just bound them to variables and used them directly. I’m still thinking about how this should work.

Conclusion

This is obviously still a toy (no sorting, doesn’t update, etc, etc), but I think shows promise. I like the separation of the structure and behavior, but the selector stuff needs more thought. Probably the biggest gain over raw Swing is that Seesaw takes care of all the yucky reify and proxy stuff for you. In this example alone, a raw implementation would need two (reify)s and a (proxy) call. Building up the widget structure is also pretty tedious with raw Swing.

I’d love to to hear feedback and criticism of the API since this is my first attempt at real Clojure code. Thanks!

clojure, open source, seesaw, swing , ,

A nice evening with the Clojure REPL

April 25th, 2011

I’ve been working on Seesaw a lot lately. It’s a Swing wrapper/dsl/whatever for Clojure and I’ve had a great time working on it. Tonight, I was testing some very simple graphics stuff I added (namely, the (push) macro) and I had a nice moment with the REPL. Here’s my session where I paint some text to an image and display it in a JFrame:

Clojure
user=> (use 'seesaw.core)
nil
user=> (use 'seesaw.graphics)
nil
user=> (use 'seesaw.color)
nil
user=> (def image (buffered-image 200 200))
#'user/image
user=> (let [g (.getGraphics image)]
 (.setColor g (to-color "#FF0000"))
 (.drawString g "This is RED" 5 20)
 (push g
   (.setColor g (to-color "#0000FF"))
   (.drawString g "This is BLUE" 5 40))
 (.drawString g "This is RED again" 5 60))
nil
user=> (frame :content (label :icon image))
#<JFrame ...>
user=>

and up pops:

All the yucky Java-y graphics calls need to be cleaned up, but I would never be able to type in the equivalent code in Java without liberal use of ctrl+space.

Ok, back to work.

 

 

clojure ,

Here Comes Clojure: A Clojure Talk in Clojure

April 6th, 2011

TL;DR: I did a talk on Clojure and wrote the slides in Clojure. Code here.

Edit: Fixed apostrophes. That’s embarrassing.

On kinda short notice I found out I was giving a talk on Clojure at this week’s CraftsmanGuild meeting in Ann Arbor. I’m not an expert, but “in the land of the blind, the one-eyed man is king” or something, so I was happy to do it. CraftsmanGuild is low pressure and fun.

So, I fired up PowerPoint, wrote a title slide, and then stared at the screen for a bit. This is no fun. Then it was the kids’ bedtime, which means I got to sit in my daughter’s room for a bit and just ponder. Like Hammock Driven Development, I guess. And as I sat there, in the glow of the nightlight, I got it: Why not implement my talk in Clojure, driven by some simple vim macros? It’s either brilliant, or really stupid.

If anything, the benefits outweighed the risks:

  • Practice Clojure while preparing my talk
  • Practice Vim while preparing my talk
  • No PowerPoint

The main risk was totally bombing in front of a friendly audience that’s just there to learn and have fun. Not too scary.

Here’s a screenshot of the title “slide”:

The implementation is super simple. Basically just a vector of strings and a current atom which points at the current slide. The advance! function moves the pointer, formats the slide (nice ascii borders and padding) and prints it.  It’s super simple, and can certainly be written better. I ran all of this in a VimClojure REPL set up as described in a previous post. There were a few cool things about this:

  • I got syntax highlighting of sample code (and admittedly, the rest of the text) for free.
  • I could immediately type examples or elaborate ideas directly in the REPL without leaving my “slides”.
  • I could evaluate code samples right from the slide and expand on them live.

I hacked (I mean they’re really kludgy) together some simple vim macros to:

  • Reload the presentation code
  • Go back to the beginning
  • Advance to the next slide
  • Evaluate the form under the cursor in the REPL. This was slightly tricky because it had to strip out the slide “borders” first.

Overall, I think the effect was pretty cool. Everything ran well, with the major problem being that the projector’s red wasn’t working so it was hard to see some of the text. Oh, and at one point I accidentally hit my caps lock with the usual confusion that accompanies it. Bygones. The actual content was probably the weakest part of the talk, but not terrible. Passable for two nights prep.

Here’s one last screenshot showing some syntax highlighting and simple ascii diagramming:

The code for the talk is all up on github: https://github.com/daveray/here-comes-clojure. Note that vim isn’t required. It will run in a normal REPL, it just won’t look as nice. And, of course, I’m sure something much more impressive is already built-in to Emacs :)

clojure, vim , ,

Say Something Nice About Every Language You’ve Used

December 8th, 2010

In Michael Easter’s recent post, I was struck by his comment that Guy Steele like all languages. Seems like a pretty chill way to live a programming career. So I wondered, do I like all languages? Can I say something nice about every language I’ve used? As the saying goes, “If you can’t say something nice, don’t say nothin’ at all.”

Let me give it a try in rough chronological order of the first time I used each language in anger:

  • Pascal - Ouch. My memory is so fuzzy I can’t even think of something bad to say about it. So we’ll count “no comment” as nice and move along …
  • C++ – Another toughy, but this time because my memory is so sharp. Hmmm. Uh. C++ has a really nice personality. Next.
  • Matlab – Pretty cool array slicing notation. I don’t know if Python stole this from Matlab, but when I first learned Python I was like “Hey, this is Matlab!”
  • Common Lisp – Generic functions and multiple dispatch are cool.
  • Visual Basic 6 – Seemless integration with COM and built-in support for the observer pattern.
  • C – As Linus has pointed out, you need almost no context to understand a random chunk of C code. It is what it is and nothing more.
  • Java – It’s simple enough that really powerful, reliable tools can be built for it. If you change the signature of a method in Eclipse, you can feel confident that it actually worked. (unless you’re doing reflection…)
  • Tcl – The entire language is expressed in 11 simple rules and it’s homoiconic. Once you accept that everything is a string, you’ll enter a zen-like trance and every atom of your being will vibrate in harmony with Tcl’s interpreter. Or something. Finally, whenever you write a quick test script, you get to name it “test.tcl”
  • Python – Python taught me about list comprehensions and bound methods. It’s stupid, but I also always liked that you could multiply a string by a number to repeat it.
  • Soar – Fast, rete-based pattern matching is cool. Everything that’s really easy in a procedural language is hard in Soar, but some things that are hard are easy.
  • JavaScript – Taught me that objects are overrated and started my reptilian, OO brain down a brighter path.
  • Ruby – I think blocks are a neat bit of syntactic sugar. I like that everything, including nil, is an object.
  • Scala – Introduced me to implicit typing and opened my eyes to how much I actually have to type when I’m coding Java.
  • Clojure – It’s fun, has a nice cross-platform VM, persistent data structures, a good concurrency story, and is apparently saving Lisp from itself.

Wow, I feel really great now.

Note that every one of these could have easily be extended with “even though”, “except for when” or “but sometimes”, but I resisted the urge, mostly.

Can you think of something nice to say?

misc, software engineering ,

Programming Etudes

December 6th, 2010

Can you implement a stack off the top of your head? How about a simple hash table? A recursive descent parser? Can you do it without thinking about it?

These are a few programming “etudes“. Musicians have a tradition of etudes designed to teach fundamental lessons about playing their instrument. They practice them (usually as children) until they can play them perfectly from memory. Just like with the programming examples above, a musician doesn’t play these etudes in “the real world”. They’re technical exercises so that when they get on stage they can make an artistic statement rather than worrying about fingerings.

A pianist practicing an etude may focus on alternate fingerings, dynamics, tempo. What are equivalent variations you could try while doing a matrix multiplication “etude”? Elegance? Performance? Generality? Obfuscation?

Build your own set of programming etudes. Practice them. They’ll make you a better programmer. Now repeat in another language.

Can you minimize key strokes in your editor? Try it in a different editor?

Can you design a series of etudes that build on each other? Maybe it’s like programming a fugue? Linked-lists + a hash function becomes a hash table. What’s next?

Can you think of etudes in your favorite framework? The “fifteen minute blog” is one. See, it doesn’t have to be all about data structures and algorithms and clever interview questions. It’s about getting the tools of your trade under your skin.

What else?

Now go read Dave Thomas’ CodeKata.

Practice, practice, practice!!

software engineering ,

Remedial Clojure: What Rhymes with Clojure? Part 1

November 11th, 2010

Previously we put together some Clojure code to parse a pronouncing dictionary from a file, URL, or other resource. Recall that the resulting structure was a map from a word to a vector of phonemes and stress info. For example:

{ "CLOSURE" [["K" nil] ["L" nil] ["OW" :p] ["ZH" nil] ["ER" :n]] }

Now we’re going to put the dictionary to use. We’ll build a datastructure and function that can find all the rhymes for a word and then, in part 2, we’ll use Compojure to make simple web front-end for it. The final result will look like this:

The final source for this post is all on github.com

Soft Rhyme Classes

Determining whether two words rhyme basically consists of comparing the phonemes from the end of the words. For example, we can see that “BETTY” and “SPAGHETTI” rhyme because they share a common three-phoneme suffix:

  • BETTY [ B - EH - T - IY ]
  • SPAGHETTI [ S - P - AH - G - EH - T - IY ]

This is known as a “hard” rhyme because the phonemes match exactly. To keep things interesting, we’ll be looking for “soft” rhymes, that is phonemes that mostly rhyme, by grouping phonemes into equivalence classes. For example, “BETTY” and “READY” aren’t hard rhymes because the “T” and “D” phonemes are different. Put them in the same soft rhyme class however, and we have a soft rhyme for those two words.

So, to get things started, let’s set up our soft rhyme classes. First we’ll define the classes themselves as sets of phonemes and then build a map from each individual phoneme to its soft rhyme class. This gives us a chance to Clojure’s set literal as well as a for list comprehension.

(def soft-rhyme-classes-seed
  ^{ :doc "Seed for soft-rhyme-classes below. These classes are based on a very
          old dead page accessible only with the wayback machine:

http://web.archive.org/web/20021018075650/http://web.utk.edu/~blyon/RhymerMiner/FranklinRhymerHelp.htm

          " }
  [#{"AA" "AO" "AW" "OW"}
   #{"AE" "EH"}
   ... more classes ...
   #{"AY"}
   #{"Y"}])

(def soft-rhyme-classes
  ^{ :doc "A map from phoneme to soft rhyme class" }
  (apply hash-map (flatten (for [klass soft-rhyme-classes-seed, phone klass] [phone klass]))))

Note that I derived these classes many years ago from a webpage that only survives in the Wayback Machine. Thanks Wayback Machine!

for allows us to iterate over the equivalence classes and then their members and generate a key/value pair for each combination. This gives us a list of phoneme/class pairs (each is a vector) which we’d like to turn into a map. Now, the hash-map function creates a map from its arguments, so we need to turn this list of pairs first into a flat list and then use that list as the arguments to hash-map. Clojure has us covered on both counts. To flatten the list, we use, of all things, flatten. Go figure:

user=> (flatten [["KEY1" "VALUE1"] ["KEY2" "VALUE2"] ["KEY3" "VALUE3"]])
("KEY1" "VALUE1" "KEY2" "VALUE2" "KEY3" "VALUE3")

To use any sequence as the arguments of a function, use apply:

user=< (apply hash-map (flatten [["KEY1" "VALUE1"] ["KEY2" "VALUE2"] ["KEY3" "VALUE3"]]))
{"KEY1" "VALUE1", "KEY2" "VALUE2", "KEY3" "VALUE3"}

I’ve found that apply is easy to forget about, but often useful. So don’t forget about it!

The Rhymer

Design

Now that we have our rhyme classes out of the way we can work on calculating all the rhymes for a particular word. This would be pretty simple to do by comparing the tail of the word with the tails of the rest of the words in the dictionary… but at 160K words, that might be slow. Instead we can create a datastructure to speed the process. The basic idea is to create a trie, or prefix tree. The twist is the keys at each level will be soft rhyme classes and we’ll uses suffixes rather than prefixes. So we’ll get something like this:

{
    #{IY ...} {
        #{T D ...} {
            #{EH ...} {
                :words [EDDIE]
                #{B ...} {
                    :words [BETTY]
                }
                #{R ...} {
                    :words [READY]
                }
            }
        }
    }
}

Note that in Clojure any of its built-in datatypes can be used as keys in a map. hashCode() and equals() are taken care of and because they’re immutable we don’t have to worry about keys changing and corrupting the hash table.

Each level of the tree contains an optional list of words, keyed by :words. It’s a list so we can correctly handle homophones such as “BEAR” and “BARE”. Each level also has keys for any further phonemes moving up the suffix of the words. So to find the rhymes for a word, we follow its phonemes in reverse down the suffix tree to a desired depth and then collect all the words in that sub-tree.

Taking “BETTY” with the rhyme tree above as an example, we first reverse its phonemes, [IY T EH B] and then do lookups for the soft rhyme classes of IY, T, EH. This will give us a sub-tree containing “BETTY”, “READY”, and any other words that end with an “-ETTY” sound.

Building the Suffix Tree

Building the rhyme suffix tree is, I think, kind of tricky, so it’s even more important to have some tests. I’m continuing to use lazytest and here we’ll meet the given macro to set up a common environment for all our tests. given works basically like let, except that its body must contain test examples rather than arbitrary expressions. I use given to load a test dictionary from the classpath and predefine some words I’ll use throughout the tests:

(describe "with a test dictionary"
  (given [resource (.. (Thread/currentThread)
                        getContextClassLoader
                        (getResource "rhymetime/test/test-dict.txt"))
          dict (parse-dictionary resource)
          lisp (dict "LISP")
          asp  (dict "ASP")
          betty (dict "BETTY")
          bear (dict "BEAR")]

    (testing make-rhyme-tree ...

Note the use of getResource to read the test dictionary from the classpath. This is better than using a plain filesystem path because it makes your tests immune to changes in the working directory. Inevitably, a raw filesystem path will work great right up until you start running your tests in a continuous integration environment like Hudson where the working directory isn’t necessarily the root of your project.

Let’s define a function called make-rhyme-tree to build the tree. Here’s a test:

(testing make-rhyme-tree
  (it "builds a rhyme tree from a pronouncing dictionary where words are
      indexed by reversed soft rhyme classes. The words at a given node
      are stored under the :words key"
    (let [tree (make-rhyme-tree dict)]
      (and
        (= ["BETTY"]       (:words (get-in tree (rhyme-tree-path-for betty))))
        (= ["LISP"]        (:words (get-in tree (rhyme-tree-path-for lisp))))
        (= ["BEAR" "BARE"] (:words (get-in tree (rhyme-tree-path-for bear))))
        (= ["ASP"]         (:words (get-in tree (rhyme-tree-path-for asp))))))))

It takes a few helper functions to implement. First we need a way to build the path (list of soft rhyme classes) from the phonemes of a word:

(defn rhyme-tree-path-for
  "Given a word pronunciation, return its path in a rhyme tree"
  [phonemes]
  (->>
    phonemes
    (map first)
    (map soft-rhyme-classes)
    reverse))

Here the ->> (thread) macro comes in handy to show the series of transforms we’re doing on the phoneme list: grab the phoneme from the phoneme/stress pair, look up the soft rhyme class, and finally reverse the whole thing since this is a suffix tree as described above. Once we have a path, we can use the get-in and assoc-in functions to work with the tree. This is much more straightforward than using just get and assoc:

(defn- add-word-to-rhyme-tree
  "Given a rhyme tree and a parsed word, add it to the tree and return
   a new tree"
  [tree [word phonemes]]
  (let [path (rhyme-tree-path-for phonemes)
        sub-tree (get-in tree path)
        words (:words sub-tree)]
    (assoc-in tree path (assoc sub-tree :words (cons word words)))))

Here we look up the current list of words (homophones) at a particular path in the tree and then cons the word into the list. We’re taking advantage of a few things here. First, assoc-in will create the entire path necessary and any missing maps along the path. Second, assoc is happy to take nil as its first parameter. It creates a new map. Similarly, cons treats nil as an empty seq:

user=> (assoc-in nil [:a :long :non-existant :path] "value")
{:a {:long {:non-existant {:path "value"}}}}

user=> (assoc nil "key" "value")
{"key" "value"}

user=> (cons "value" nil)
("value")

Little touches like this help make Clojure code much more compact than equivalent Java code which would be riddled with checks for null. This nil-handling also plays an important part in laziness.

Now, given a dictionary, we can pull this together to build the full rhyme tree. It’s a little anti-climactic:

(defn make-rhyme-tree
  "Make a rhyme tree from a pronouncing dictionary. This constructs the
   raw tree structure. See make-rhymer for the actual rhyme calculation"
  [dict]
  (reduce add-word-to-rhyme-tree {} dict))

Just apply add-word-to-rhyme-tree to the key/values in the dictionary, accumulating into an initially empty map. For the reasons given above, the initial value could also just be nil, but I think {} makes it clearer that we’re iteratively filling in a map.

Implementing Lookup

Now that we’ve got our suffix tree, we just need a function for looking up rhymes. We’ll define a function that, given a dictionary, returns a function we can use to look up rhymes. I think this kind of “encapsulation” is a neat feature of functional programming. Rather than having to keep track of the context (the dictionary) and always pass it to some function, like the make-rhyme-tree test above, we capture the context in a closure and return a function (or functions) to operate on that context.

Continuing from our tests above, here’s the test for our “rhymer” function:

(testing make-rhymer
  (it "returns a function that calculates rhymes for a word"
    (let [rhymer (make-rhymer dict)]
      (= #{"BETTY" "READY" "SPAGHETTI" "MACARONI"} (set (rhymes "MACARONI" 1)))
      (= #{"BETTY" "READY" "SPAGHETTI" }           (set (rhymes "BETTY" 2)))))
  (it "returns a function that returns an empty seq for unknown words"
    (let [rhymes (make-rhymer dict)]
      (empty? (rhymes "MACARONIX" 1)))))

We turn results into sets so we don’t have to worry about the ordering of the results.

Now, to implement this we need to look up a sub-tree for a word and then collect all the words in that sub-tree. Preferably, the returned sequence of words should be lazy because it’s good to be lazy. It took me quite a while to come up with the right approach for this, and I’m definitely not convinced this is the best approach:

(defn- collect-words-in-sub-tree
  "Returns a lazy seq of all the words in the :words keys of the given sub-tree."
  [coll]
  (lazy-seq
    (when-let [s (seq coll)]
      (let [[k v] (first s)
            r (rest s)]
        (concat (if (= :words k)
                  v
                  (collect-words-in-sub-tree v))
                (collect-words-in-sub-tree r))))))

As described in Programming Clojure, this seems to be the canonical pattern for the usage of the lazy-seq macro. lazy-seq returns a seq-able object that doesn’t actually invoke any code until the first time it’s used. The pattern is basically, do whatever you’d normally do in a recursive way, and then wrap it in lazy-seq. It’s common to have a when-let test to end recursion and then a let which grabs the first item which is processed, and rest of the collection which is used for the recursion.

Here I test whether I’m looking at the :words key. If I am, I use it, otherwise it’s another node so we recurse. Also of interest is the use of the destructuring [k v] in the let. This is one of my favorite features of Clojure so far.

As I mentioned, it took me a while to get to this point. I’m sure it will get easier with experience, but any pointers or guidance would be appreciated.

Now let’s finally make our rhymer function:

(defn make-rhymer
  "Returns a function that can lookup up rhymes for a word in the given dictionary"
  [dict]
  (let [tree (make-rhyme-tree dict)]
    (fn [word depth]
      (when-let [phonemes (dict word)]
        (let [path     (take depth (rhyme-tree-path-for phonemes))
              sub-tree (get-in tree path)]
          (collect-words-in-sub-tree sub-tree))))))

This function has two parts. The outer let is where we build the rhyme tree. Then we return an anonymous function which takes a word and a depth and returns a list of rhymes. The rhyme tree is captured by the anonymous function giving the encapsulation mentioned above. Otherwise, the implementation is pretty mundane. Look up the word in the dictionary, use its phonemes to do a lookup in the rhyme tree, and return the list of rhyming words. Yay, we’re done!

Here’s an example usage at the repl. Note that I had to bump the max heap size of the JVM to 512MB to load the full CMU dictionary (-Xmx512M):

user=> (use 'rhymetime.pronounce)
nil

user=> (use 'rhymetime.rhyme)
nil

user=> (def dict (parse-dictionary "https://cmusphinx.svn.sourceforge.net/svnroot/cmusphinx/trunk/cmudict/cmudict.0.7a"))
#'user/dict

user=> (def rhymer (make-rhymer dict))
#'user/rhymer

; helper to set the depth to (# of phonemes - 1)
user=> (defn h [w] (rhymer w (dec (count (dict w)))))
#'user/h

user=> (h "CLOSURE")
("FORECLOSURE" "ENCLOSURE" "INCLOSURE" "ENCLOSURE(1)"
 "DISCLOSURE" "ZLOGAR" "CLOSURE" "CLOTURE" "CLOSER(1)"
 "LOESER" "LOSURE" "LOGAR" "LOKER" "LOESCHER" "PLOEGER")

user=> (h "MONAD")
("NOMAD" "MONAD" "NANDONET" "AUTOMAP" "GLYCOMED(1)"
 "GONAD" "BIOMET" "BIOMED")

user=> (h "JAVA")
("MOFFA" "NAVA" "GUAVA" "HOFFA" "SAVA" "SCOZZAFAVA" "FAVA" "RYAVA"
 "LACAVA" "PENKAVA" "RUBALCAVA" "CAVA" "JAVA" "ACTAVA" "VOTAVA"
 "BOFFA" "BAVA" "GUSTAVA" "MUSTAFA" "SRIVASTAVA" "SRIVASTAVA(1)"
 "STAFFA" "SLAVA" "BRATTASLAVA" "LAVA")

Conclusion

That wasn’t so hard. The more you work with Clojure, the more you get a feel for how the various seemingly simple pieces can be composed to build powerful software. In part 2, we’ll take what we built here and build a web-based UI for it using Compojure. Until then, keep Clojuring.

clojure , ,

Compojure, the Repl, and Vars

November 5th, 2010

For a future post, I’ve been working on a simple webapp using Compojure, a simple web framework for Clojure. Working with Compojure interactively in the repl gets mentioned a lot, but never with very satisfying answers. So tonight I worked through it and believe I have a reasonable approach that covers everything I want, namely:

  • The ability to start the server in the background of the repl
  • The ability to stop the server in the repl
  • The ability to reload code, hit refresh on the browser, and see my changes

I’ve seen several posts that have a separate namespace (i.e., .clj file) for running the server. This didn’t seem necessary in my tests. Assmuing we’re in web-app.core (src/web_app/code.clj), define your routes and a run function like this:


(defroutes all-routes
  ... route definitions ...)

(defn run
  [options]
  (let [options (merge {:port 8080 :join? true } options)]
    (run-jetty (var all-routes) options)))

There are a couple semi-interesting things going on here. First, we have some default options for the server. When (run) is called, its default behavior is to run the server on port 8080 and block (because of the join? flag, which is important once we’re in the repl).

Secondly, rather than passing all-routes directly to run-jetty, we pass in (var all-routes) (or the #'all-routes reader macro). This way, when we reload our code, the server is using the Var rather than having its own copy. When the root binding changes, the server picks it up without having to restart (see below for a simple example).

Finally, we can use this in the repl:


  ;;; Load the web-app
  user=> (use 'web-app.core :reload)
  nil

  ;;; Run the server with join? false so it doesn't block the repl
  ;;; Also save the result so we can stop the server later
  user=> (def server (run {:join? false}))
  #'user/server
  2010-11-05 20:46:32.797::INFO:  Logging to STDERR via org.mortbay.log.StdErrLog
  2010-11-05 20:46:32.800::INFO:  jetty-6.1.14
  2010-11-05 20:46:32.903::INFO:  Started SocketConnector@0.0.0.0:8080

  ;;; Now test the webapp, make some changes to the code, and ...
  user=> (use 'web-app.core :reload)
  nil

  ;;; Now make sure the changes took effect. Yay!
  user=> (use 'web-app.core :reload)
  nil

  ;;; If we need to, we can stop the server and restart it too!
  user=> (.stop server)
  nil
  user=> (def server (run {:join? false}))
  #'user/server
  2010-11-05 20:48:02.022::INFO:  jetty-6.1.14
  2010-11-05 20:48:02.046::INFO:  Started SocketConnector@0.0.0.0:8080
  nil
  user=> 

That’s about it. Way better than restarting the repl on every code change. I bet there’s much slicker way to do this in Compojure, but I haven’t found it yet.

Var?

As mentioned above, passing the var of the request handler is key to having changes take effect when the code is reloaded. Here’s a very simple example of this behavior outside of the webapp context:


  user=> (defn greet [] (println "Hi!"))
  #'user/greet
  user=> (greet)
  Hi!
  nil
  user=> (defn call [f] (f))
  #'user/call
  user=> (call greet)
  Hi!
  nil
  user=> (def wrap (partial call greet))
  #'user/wrap
  user=> (wrap)
  Hi!
  nil
  user=> (defn greet [] (println "HEY!"))
  #'user/greet
  user=> (wrap)
  Hi!
  nil

  ;;; Note that it still prints "Hi!".
  ;;; Let's try that again, but use var instead

  user=> (def wrap (partial call (var greet)))
  #'user/wrap
  user=> (defn greet [] (println "Hi!"))
  #'user/greet
  user=> (wrap)
  Hi!
  nil
  user=> (defn greet [] (println "Hey!"))
  #'user/greet
  user=> (wrap)
  Hey!
  nil

  ;;; This time the change to greet took affect!

clojure , ,

A Brief Note on Compojure Routes and Requests

November 3rd, 2010

This post is mostly for my own reference, but hopefully someone else will find it helpful. I’ve been playing with Compojure and, maybe because it’s a young framework, have found up-to-date documentation and examples hard to come by. I think this is exacerbated by the fact that Compojure was broken up (I think) into Ring, Clout, Hiccup etc.

Note that I’m using Compojure 0.5.2. Hopefully this info applies to future versions.

Anyway, the problem I had, which seemed really simple, was getting query parameters from the request in route rules. In a lot of ways, my reptillian, Java-poisoned brain was overthinking the issue. Once I stepped back and thought about it, here are the simple rules that became clear to me:

  • The second argument to the GET macro (or POST, etc) is a binding form. If you give it just a symbol, you’ll get the entire request map (see below)
  • The request binding form can use destructuring to pull out the parts of the request map you need.
  • If an entry in defroutes table returns nil for any reason (say you’re just trying to print a query parameter, but you have a typo), Compojure moves on and tries the next entry.

That’s it. I know, I know … dumb, but coming from languages with syntax and lots of “special forms”, it’s easy to let Clojure trick you into thinking there’s more to something than there really is.

Finally, and the real reason for this post, is “What does the request map actually look like, so I know what I can destructure from it?!?”. Here’s a dump of the request map I made once the lightbulb came on:


{
  :body               #<Input org.mortbay.jetty.HttpParser$Input@3e1d25>
  :character-encoding nil,
  :content-length     nil,
  :content-type       nil,
  :cookies            {},
  :form-params        {},
  :params             {"word" "bar"},
  :query-params       {"word" "bar"},
  :query-string       "word=bar",
  :remote-addr        0:0:0:0:0:0:0:1,
  :request-method     :get,
  :route-params       {},
  :scheme             :http,
  :server-name        "localhost",
  :uri                "/foo",
  :server-port        8080,
  :headers {
    accept          text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,
    accept-charset  ISO-8859-1,utf-8;q=0.7,*;q=0.7,
    accept-encoding gzip,deflate,
    accept-language en-us,en;q=0.5,
    connection      keep-alive,
    host            localhost:8080
    keep-alive      300,
    user-agent      Mozilla/5.0 ...,
  },
}

One thing to note is that the keys of :params and :query-params are Strings, not keywords!

Destructure away.

clojure ,