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