Here's my version. Main points: * Use with-open & line-seq for worry-free laziness * Do everything in one swoop (reduce) * Perform one regexp match per line * Leverage ->>
;; (ns user (use [clojure.java.io :only [reader]])) (def re-vote #"([A-z]{1,16})(\+\+|\-\-)") (defn extract-votes [line] (map rest (re-seq re-vote line))) (defn reckon [log] (with-open [r (reader log)] (let [votes (mapcat extract-votes (line-seq r))] (reduce (fn [tally [nick vote]] (let [inc-or-dec (if (= vote "++") inc dec)] (assoc tally nick (inc-or-dec (tally nick 0))))) {} votes)))) (defn -main [& [[log]]] (let [tally (->> log reckon (remove (comp zero? val)) (sort-by (comp - val)))] (doseq [[nick score] tally] (println nick score)))) Hope that helps, Justin On Dec 21, 8:38 pm, Marek Kubica <ma...@xivilization.net> wrote: > Hi, > > I wrote a small log file analyzer for IRC logs. We use nickname++ and > nickname-- to track the "karma", so after trying to write it in > JavaScript (failed due to to the fact that Gjs/Seed are unmature yet), > Factor (failed because I am just too stupid to understand it), Guile > (failed because I ran into encoding/regex-problems), so I gave Clojure > a try. > > I really liked the immutable data stuctures, so I tried to avoid > mutation. > > So uhm, this is my first Clojure program. I tend to learn a lot from > code reviews and would be happy if someone could take a look at it and > tell me what to improve and how to write more idiomatic code. > > Code is here, and reproduced below: > <https://github.com/Leonidas-from-XIV/karmawhore/blob/68ff6b681c5862fa...> > > Thanks in advance! > > regards, > Marek > > (ns net.xivilization.karmawhore > (:gen-class) > (:use [clojure.contrib.duck-streams :only (read-lines)])) > > (def allowed-nickname "[A-z]{1,16}") > (def nick-plus (re-pattern (format "(%s)\\+\\+" allowed-nickname))) > (def nick-minus (re-pattern (format "(%s)\\-\\-" allowed-nickname))) > > (defn extract-nicks [regexp line] > (map second (re-seq regexp line))) > > (defn modify-karma [op h nick] > (let [current-value (h nick)] > (if (nil? current-value) (assoc h nick (op 1)) > (assoc h nick (op current-value 1))))) > > (def increase-karma (partial modify-karma +)) > (def decrease-karma (partial modify-karma -)) > > (defn process-line [acc line] > (let [nicks-add (extract-nicks nick-plus line) > nicks-sub (extract-nicks nick-minus line) > after-add (reduce increase-karma acc nicks-add)] > (reduce decrease-karma after-add nicks-sub))) > > (defn -main [& args] > (let [file-name (first (first args)) > histogram (reduce process-line (hash-map) (read-lines > file-name)) nonzero? (comp not zero? second) > histogram (filter nonzero? histogram) > sorted-by-karma (sort-by #(- (second %)) histogram)] > (doseq [item sorted-by-karma] > (printf "%s %d\n" (first item) (second item))))) > > (-main *command-line-args*) -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en