I can't claim to be an experienced Clojure developer, specially so 
regarding maintainability as I'm the only reader of what I write. Andy 
provided a great piece of code, although I scratched my head for a second 
or two unwrapping the last two lines. You'll be surprised how often 
(partition * 1) comes up, as it provides a sliding window through a 
sequence.

(BTW, Andy, how do you format your code so prettily?)

Regarding your question about expecting a sorted input: why don't you 
ensure it? These are the (very similar) options to enforce a precondition 
that I know of:










*(defn hr-zone [bpm [zone-1 zone-2 zone-3 zone-4 :as zones]]  {:pre [(< 
zone-1 zone-2 zone-3 zone-4)]} ...) ; I don't see this very often, but it's 
simple(defn hr-zone [bpm [zone-1 zone-2 zone-3 zone-4 :as zones]]  (assert 
(< zone-1 zone-2 zone-3 zone-4)} "Not sorted!") ...) ; throws an error just 
as the above one, but with a provided message(defn hr-zone [bpm [zone-1 
zone-2 zone-3 zone-4 :as zones]]  (when-not (< zone-1 zone-2 zone-3 
zone-4)} (throw (Exception. "Not sorted!"))) ...) ; If you want to be able 
to catch the error, you may throw an exception*sorted? does not do what you 
may expect: it tests whether the data structure implements Sorted, such as 
sorted-set and sorted-map. You may get the same behaviour with (apply <= 
coll) or (apply < coll) for numeric collections.

For me, the simplest option is




*(defn hr-zone [bpm zones]  (let [[zone-1 zone-2 zone-3 zone-4] (sort 
zones)]    ...)*
which never fails, although may not be what you need (for example, you'd 
like to be alerted if you input [174 178 128 186] when you wanted [174 178 
182 186]).

Hope that helps a bit,

Bruno Kim.

On Sunday, February 16, 2014 7:31:46 PM UTC-3, Laurent Droin wrote:
>
> Hi,
>
> Disclaimer - I am completely new to Clojure. I just implemented my very 
> first (simple) program, letting me find out, from a GPX file, how much time 
> is spent in the various heart rate zones. Now that it's working, I'm 
> reviewing the code and trying to use best practices. From what I have read 
> so far, there are many ways in Clojure to do the same thing and for a 
> newbie, it's not always obvious to get a good grasp on what is the best way 
> to  code a feature.
> As a developer, and even though I love how concise Clojure programs can 
> be, I am very concerned with readability and ease of maintenance so I would 
> like to keep functions as short and tight as possible, but not to the point 
> where it becomes hard to understand what it does.
>
> Here is a function that I came up with that takes  a bpm (heart beats per 
> minute) value, as well as a sequence of 4 values that represent the 
> boundaries defining the 5 different heart rate zones for a particular 
> person.
> The function needs to finds out in what heart zone the bpm value falls 
> into and return that zone (as a keyword - I later use that keyword in a 
> map).
>
> If you're an experienced Clojure developer, what would you have done 
> differently (and why) ?
>
> *(defn hr-zone*
> *  "Return the HR zone as a keyword according to the bpm value."*
> *  [bpm [max-zone-1 max-zone-2 max-zone-3 max-zone-4]] *
> *  (cond *
> *    (<= bpm max-zone-1) :hr-zone-1*
> *    (and (< max-zone-1 bpm) (>= max-zone-2 bpm)) :hr-zone-2 *
> *    (and (< max-zone-2 bpm) (>= max-zone-3 bpm)) :hr-zone-3 *
> *    (and (< max-zone-3 bpm) (>= max-zone-4 bpm)) :hr-zone-4 *
> *    (< max-zone-4 bpm) :hr-zone-5))*
>
> FYI, here is how I call this function in the REPL:
> (def my-hr-zones-defs [120 150 165 180])
>
> (hr-zone 115 my-hr-zones-defs)
> (hr-zone 133 my-hr-zones-defs)
> (hr-zone 161 my-hr-zones-defs)
> (hr-zone 175 my-hr-zones-defs)
> (hr-zone 192 my-hr-zones-refs)
>
> Questions I have:
> Would that make sense to consider (and maybe enforce) that the sequence 
> received as parameter is sorted? If this was the case, I would assume I 
> could avoid the "and" calls- assuming that all the conditions in the cone 
> form are evaluated in order. 
> Assuming that I need to test bpm against the two boundaries of each range, 
> would there be a better way to do this:
> *(and (< max-zone-1 bpm) (>= max-zone-2 bpm))*
> ?
> Maybe this would work, but is it preferable?
> *(< max-zone-1 bpm (dec **max-zone-2**))*
>
> *Thanks in advance for the advice.*
>
> *Laurent. *
>
>

-- 
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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to