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 <[email protected]> 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 [email protected]
> 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%[email protected]>
> 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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en