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
(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+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to