I use quite a few of these in my Overtone rendering of
Bach<http://skillsmatter.com/podcast/home/functional-composition>
:

; Defining a scale function from intervals

(defn sum-n [series n] (reduce + (take n series)))

(defn scale [intervals]
  (fn [degree]
    (if-not (neg? degree)
      (sum-n (cycle intervals) degree)
      ((comp - (scale (reverse intervals)) -) degree))))

(def major (scale [2 2 1 2 2 2 1]))

(major 2)


; Defining a time function

(defn bpm [beats] (fn [beat] (-> beat (/ beats) (* 60) (* 1000))))

((bpm 90) 3)


; Defining a simple canon (like row, row, row your boat)

(defn canon [f] (fn [notes] (concat notes (f notes))))

(defn shift [point] (fn [notes] (map #(->> % (map + point) vec) notes)))
(defn simple [wait] (shift [wait 0]))

(canon (simple 4))

Code's on 
github<https://github.com/ctford/goldberg/blob/SkillsMatter-2012/src/goldberg/variations/canone_alla_quarta.clj>
.

Cheers,

Chris

On 9 August 2012 05:44, Ben Mabey <b...@benmabey.com> wrote:

> On 8/8/12 10:48 AM, Brian Marick wrote:
>
>> I'm looking for medium-scale examples of using function-generating
>> functions. I'm doing it because examples like this:
>>
>> (def make-incrementer
>>       (fn [increment]
>>         (fn [x] (+ increment x))))
>>
>> ... or this:
>>
>> (def incish (partial map + [100 200 300]))
>>
>> ... show the mechanics, but I'm looking for examples that would resonate
>> more with an object-oriented programmer. Such examples might be ones that
>> close over a number of values (which looks more like an object), or
>> generate multiple functions that all close over a shared value (which looks
>> more like an object), or use closures to avoid the need to have some
>> particular argument passed from function to function (which looks like the
>> `this` in an instance method).
>>
>> Note: please put the flamethrower down. I'm not saying that "looking like
>> objects" is the point of higher-order functions.
>>
>> I'll give full credit.
>>
>>
> Oh, I have the perfect one that I actually had to write the other day.
>  (The funny thing was that I wrote the exact same functionality in Ruby
> several years ago.. I like the clojure version much better).  I'll let the
> code and midje facts speak for themselves:
>
> ;; some context: 
> http://en.wikipedia.org/wiki/**Urn_problem<http://en.wikipedia.org/wiki/Urn_problem>
> (defn urn
>   "Takes a coll of pairs representing a distribution with keys being the
> probability of the corresponding values.
>
> Returns a function that when called will return a random value based on
> that distribution.
>
> Example:
>
>  (def multimnomial-urn (urn [[0.3 :red] [0.5 :black] [0.2 :green]]))
>
>  (take 5 (repeatedly multimnomial-urn)) => [:red :black :black :red :green]
> "
>   [dist]
>   {:pre [(= 1.0 (reduce + (map first dist)))]}
>   (let [range-dist (last (reduce (fn [[total pseudo-cdf] [percent val]]
>                                    (let [new-total (+ percent total)]
>                                      [new-total (assoc pseudo-cdf
> new-total val)]))
>                                  [0.0 (sorted-map)]
>                                  dist))]
>     (fn []
>       ;; TODO: use a better PRNG
>       (let [rn (rand)]
>         (val (find-first #(< rn  (key %)) range-dist))))))
>
> ;;; test code
> (ns foo.core-test
>   (:use midje.sweet
>         foo.core
>         [useful.map :only [map-vals]]))
>
> (defn ratios [m]
>   (let [freqs (frequencies m)
>         total (reduce + (vals freqs))]
>     (map-vals freqs #(/ % total))))
>
> (defn percentages [m]
>   (-> m ratios (map-vals double)))
>
> (facts "'#urn"
>   (let [rand-key (urn [[0.3 :foo] [0.7 :bar]])]
>     (percentages (repeatedly 100 rand-key)) => (just {:foo (roughly 0.3
> 0.1)
>                                                       :bar (roughly 0.7
> 0.1)})))
>
>
> ;;; end code
>
>
> Hopefully I understood the question and this helps some.  For an example
> in a book you could make it a bit simpler where the urn could only contain
> two potential values (binomial urn).
>
>
> -Ben
>
>
> --
> 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+unsubscribe@**googlegroups.com<clojure%2bunsubscr...@googlegroups.com>
> For more options, visit this group at
> http://groups.google.com/**group/clojure?hl=en<http://groups.google.com/group/clojure?hl=en>
>

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