I'm also very new to clojure but this is how I'd do it:

(def hr-zones {
   [0 100] :low
   [101 120] :fat-burn
   [121 140] :aerobic
   [141 160] :anaerobic
   [161 333] :max})

(defn hr->zone [hr]
  (some (fn [x]
    (and (<= (first (key x)) hr (second (key x)))
         (val x)))
    hr-zones))


This method does have some disadvantages however (you have to make sure the 
boundaries are correct and it doesn't handle floating points like 140.4).

Whenever you see yourself repeating code (like the 3-4 if's you have) then 
you have to take a step back and maybe change your data structure so that 
your algorithm is easier.

Mathematically speaking you're really quantizing your data (aka applying a 
piecewise constant function). So you could even take another step back and 
make it more general. So find a data structure that represents the function 
(ie the intervals and the function value for each interval) and then you 
could come up with a function like "quantize" or "mk-piecewise-const-fn" 
that returns a function. So you could then do:

(let [myfn (mk-piecewise-const-fn [[100 :zone-1] [120 :zone-2] ...] ]
       myzone (myfn 142)]

and you have a general function  which you can now use with a much wider 
range of problems (not just specific to your hr->zone conversion).

But I'm too lazy to come up with a implementation for mk-piecewise-const-fn 
:)

HTH


On Sunday, February 16, 2014 5:31:46 PM UTC-5, 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