Further into Chapter 4
So I haven’t posted for a while. Many things happened over the past few weeks, including a trip to Boston to attend PAX East and my parents visiting for the weekend. I’ve found myself yearning to get back to Clojure, which is as good a sign as any that I’m approaching coder obsession. So, onward!
First, a bit of advice: If you’re learning a new programming language, you absolutely have to keep at it every single day, even if you only do a little. It’s only by daily reinforcement that you can solidify the lessons and syntax you learn as you progress. Immediately upon reopening my files and starting up the autotests I found myself struggling to remember what types were appropriate for what I was trying to do. It took much longer than it should have for me to complete the next stage of the game’s development.
I started running into some difficulty given that CLISP doesn’t have all the types that Clojure does, and has much simpler quote/unquote splicing. In Clojure, unquotes automatically fully-qualify any symbols within the unquoted sequence, leading to:
(there is a (clojure.core/unquote (last edge)) going (clojure.core/unquote (second edge)) from here)
Yeah, and after much fiddling around with this I was given advice to try using strings, which Clojure has the ability to manipulate in the way that I wanted. So here’s what I came up with for describe-location and describe-path and describe-paths
(def ^:dynamic *edges*
{:living-room ['[garden west door]
'[attic upstairs ladder]]
:garden ['[living-room east door]]
:attic ['[living-room downstairs ladder]]})
(defn describe-location
"Describe the location in the node map. Really it's just
an alias for 'get'."
[location nodes]
(get location nodes))
(defn describe-path
"Describes a path from the edges map."
[edge]
(str "there is a " (last edge) " going " (second edge) " from here."))
(defn describe-paths
"Describe all paths from a location given an edges map"
[location edges]
(join " " (map describe-path (get *edges* :living-room))))
One thing I’m becoming very unhappy with is the use of earmuffs for global variables. When I do them without the def &:dynamic *var* style Clojure buzzes irritation at me, but in this case *edges* is not dynamic and doesn’t need to be, so I’m inclined to just remove the earmuffs and make it a regular def.
As you can see I chose to use a map for the edges, just like what I used for nodes. Vectors describe the non-executable set of symbols describing the edge, but I”m not 100% certain it’s the right type for that data. I pulled clojure.string/join in because I discovered that str concatenates without spaces. The join function was usable without apply, and gradually with some testing in the REPL the solution came together and I got some passing tests!
I’ll continue working on it tomorrow. With more frequent efforts comes more progress and confidence!