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
-~----------~----~----~----~------~----~------~--~---

Reply via email to