Parts 1 through 6 of this series can be found here, here, here, here, here and here.
Alright, so I kind of just remembered that there was still one chapter left to go – so here it is! Until _why decides to come out of hiding and write an 8th chapter (whenever that happens, if ever…), this will be the final installment of my translation of _why’s (poignant) guide to ruby into Clojure.
This is kind of a weird chapter in that the whole thing is hand-drawn (by one of the foxes, presumably), making the actual code examples a little hard to find. I feel like I’ve hit all the important bits that would constitute “examples.” This is kind of a short chapter in terms of code content, but it’s a fun one nonetheless. We’ve got a very brief example of how you might build a text adventure game using classes and metaprogramming, a function that takes a string and turns it upside-down, an example of overloading an arithmetic operator to work on arrays, and an interesting encryption algorithm.
Chapter 7
; ex. 1:(defprotocol Actions(look[room])(stab[room])(sleep[room]))(defrecord BanquetRoom[]Actions(look[_]"Red with mirrors")(stab[_]"The room screams!")(sleep[_]"Ahh, you slept on food"))(print "Banquet Room. Do what?")(let [what-to-do(clojure.string/trim(read-line))](eval `(~(symbol what-to-do)(BanquetRoom.)))); ex. 2:(defn umop-apisdn[txt](let [in"ahbmfnjpdrutwqye"out(reverse in)in-out(zipmap inout)](apply str (reverse (map #(in-out%%)txt))))); ex. 3:(def divide/)(defmulti / (fn [arg1arg2&more](and (coll?arg1)(number?arg2))))(defmethod / false[&args](apply divideargs))(defmethod / true[colln](partitionnnnilcoll))(/ [:mad:bone:and:his:buried:head]3)(/ (range 111)5)
I noticed in the “Decody” example that _why made a small, but confusing mistake when commenting his code: In the lines of code referring to 2 letters on the same row, he commented “on the same column,” and vice versa. I have corrected this for the sake of clarity (and to avoid confusing myself!).
; ex. 4:(defprotocol Encoding(locate[decodyletter])(at[decodyrowcol])(encode[decodytxt]))(defrecord DeCody[key]Encoding(locate[_letter](let [i(.indexOfkey (str letter))][(int (/ i5))(rem i5)]))(at[_rowcol](get key (+ (* row5)col)))(encode[decodytxt](let [pairs(->>(clojure.string/replacetxt#"[^a-z]""")(#(clojure.string/replace%"j""i"))(partition22nil)(mapcat (fn [[ltr1ltr2]](cond (nil? ltr2)[[ltr1\x]](= ltr1ltr2)(repeat 2[ltr1\q]):else[[ltr1ltr2]]))))](apply str (mapcat (fn [pair](let [[l1l2:asls](map #(locatedecody%)pair)](cond(= (first l1)(first l2)); on the same row(letfn[(move-right[[rowcol]][row(rem (inc col)5)])](map #(apply atdecody(move-right%))ls))(= (last l1)(last l2)); on the same column(letfn[(move-down[[rowcol]][(rem (inc row)5)col])](map #(apply atdecody(move-down%))ls)):else; normal swap[(atdecody(first l1)(last l2))(atdecody(first l2)(last l1))])))pairs)))))(defn decody[key]"Takes a string with arbitrary whitespace and removes all whitespace and other non-letter characters, returning a DeCody instance with the resulting string as a key (25 letters arranged in a 5x5 grid)."(DeCody.(clojure.string/replacekey #"[^a-z]""")))(def dc(decody"k x z p w i g t f a h o s e n y m b r c u l q d v")); example usage:(encodedc"message to be encoded")