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

Reply via email to