

Tackling my first Clojure project, a Graphical HTTP Benchmarker in Clojure - andrewvc
http://blog.andrewvc.com/tackling-my-first-jlojure-project-a-graphical

======
ibdknox
Cool project! I looked over your code very briefly and noticed you don't tend
to use destructuring very much. It was something that took me a while to get
used to too, but it turns out to be very useful and makes the code much
smaller. Take for example this:

    
    
        (defn stats [requests-state]
            "Returns a mapping of RequestsState http states states to counts"
            (reduce
                (fn [stats request]
                (let [r        @request
                        state    (:state  r)
                        status   (:status r)
                        statuses (:statuses stats)]
                    (assoc stats
                        :total     (inc (stats :total 0))
                        state      (inc (stats state  0))
                        :statuses  (assoc statuses status (inc (statuses status 0)))
                        :progress  (if  (not=  state :untried)
                                        (inc  (stats :progress 0))
                                        (stats :progress 0)))))
                    {:statuses {}}
                    (flatten (:grid @requests-state))))
    

Could be written like so:

    
    
        (defn stats [requests-state]
            "Returns a mapping of RequestsState http states states to counts"
            (reduce
                (fn [{statuses :statuses total :total :as stats} request]
                (let [{state :state status :status} @request]
                    (assoc stats
                        :total     (inc (or total 0))
                        state      (inc (stats state  0))
                        :statuses  (assoc statuses status (inc (statuses status 0)))
                        :progress  (if  (not=  state :untried)
                                        (inc  (stats :progress 0))
                                        (stats :progress 0)))))
                    {:statuses {}}
                    (flatten (:grid @requests-state))))

~~~
ataggart
You can also avoid the duplicated key/sym names:

    
    
        (fn [stats request]
          (let [{:keys [statuses total]} stats
                {:keys [state status]}   @request]
            ...))

------
daveray
Good stuff. I'm not sure if this is an improvement, but it's a nice piece of
trivia... your status range checks can be reduced a bit:

    
    
        (and (>= status 200) (< status 300))
    

becomes:

    
    
        (<= 200 status 299)
    

Go Clojure.

~~~
andrewvc
Very cool. It's not an easy call, as its esoteric syntax, but I think I'll put
it in.

------
joevandyk
I'd love to get more into Scala and Clojure, but I don't know the first thing
about Java, especially the Java ecosystem (war's, ant, jvm's, etc).

Unfortunately, most books/articles on Clojure and Scala assume you know Java.

~~~
technomancy
Knowing how to write Java is absolutely not needed at all. Knowing how to
_read_ Java can be useful depending on what libraries you need. The one thing
that you have to learn no matter what is the basic IO classes, which are
covered pretty well in <http://copperthoughts.com/p/clojure-io-p1/>.

Before the clojure.java.io namespaces was created, it used to be necessary to
interact directly with those classes for even basic usage. (Kids these days!
They've got it so easy.)

The web application ecosystem can be a bit intimidating to peace-loving
programmers with all its talk of wars, but even that is changing with
deployment options like Elastic Beanstalk and Heroku.

Anyway, you hear horror stories about Enterprise Java Beans, dependency
injection frameworks, Maven, and whatnot, but you never see any of that in
everyday Clojure.

