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