On Tue, 23 Jun 2009 18:23:01 +0200 Christophe Grand <christo...@cgrand.net> wrote:
> I think you could simplify your code by using map twice. What about: > (untested) > > (defn weighted-moving-average > "Generate a lazy sequence consisting of weighted moving averages > over the input sequence. The weighting is given by weight-fn, > having a domain 0..1 which will be scaled across win-size elements to > calculate the weighting." > [weight-fn win-size input] > (let [weights (reverse (for [t (range 1 (inc win-size))] > (weight-fn (/ t win-size)))) > weight-sum (reduce + weights) > normalized-weights (map #(/ % weight-sum) weights) > avg #(reduce + (map * normalized-weights %))] > (map avg (partition win-size 1 input)))) Hmm, yes that is certainly simpler. This actually reminds me of something that I've "felt" for awhile but haven't been able to articulate: A lot of functional programming literature takes great pains to explain how higher-order functions, lambda expressions, closures, etc work, and so I feel like I have a fairly solid grasp of the mechanics of many functional concepts. I could probably even give you a passable explanation for how to implement lexical scoping. But, I still sometimes find it challenging to spot patterns that can be replaced and simplified with HOFs and other functional idioms, and I haven't come across any books/guides that help hone one's intuition for doing this. This is a good example because, while I have no trouble at all understanding your implementation, I doubt I would have ever thought of it myself! I wonder if anyone has a guide or tips or rules of thumb to help with this, or if it just takes experience... As an aside, I also notice you prefer 'reduce to 'apply when using arithmetic functions, yet I've seen both in the wild. I'm just guessing you prefer to make it explicit that you're doing a reduction, but I wonder if one is better than another? > > btw, why the 'reverse in weights? > I found it makes it easier to think about the weighting function if (weight-fn 0) evaluates to the weight of the most recent sample (the latest in the sequence), but the 'for comprehension generates them with (weight-fn 0) as the first element in the sequence. I suppose, it would be more efficient to have 'range generate the series in reverse to begin with, wouldn't it? :) -Kyle --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---