You should treat rand and friends like i/o.  Don't bury them deep in your code. 
 Write your pure functions so that they take a seed value (or sequence).  
Generate the random values from outside of the important functions,  maybe 
providing a convenience wrapper function around your main logic.

(defn foo-pure [val seed] ...)

(defn foo-uses-rand [val] (foo-pure val (rand)))


On Dec 5, 2012, at 1:48 PM, JonC <jonathan.co...@gmail.com> wrote:

> Ok: first of all, Clojure has outstandingly the best core library I've seen. 
> I am awed by how wonderfully the protocol approach makes data structures, and 
> the good taste applied to getting an API that's reasonably minimal and 
> wonderfully complete. I've not posted before because I've had nothing to ask 
> - everything is super-clear, especially now I have a copy of JoC. But I would 
> suggest that there is one easily corrected area where things are imperfect: -
> 
> One of the big advantages of functional coding to me is rock solid 
> testability - same inputs, same outputs; easy to test, easy to debug. 
> 
> Obviously psuedo-random  numbers and io present problems with this. Now, the 
> normal way for an API to discourage something problematic is to make it 
> difficult, and to encourage correct behavoiur by making it easy. So list's 
> lack of nth but possession of first, second rest and last shout out "Do NOT 
> use for random access!" while vector's api says "Use me instead!"
> 
> Now we come to rand, rand-int, rand-nth. They're the easiest things to use 
> for their purpose, so they shout "Use me!" But.. they break the repeatability 
> paradigm. Because they use Java's default random number generator instance, 
> which has a private and unsettable seed, you can't get repeatabilty. In Java, 
> this isn't actually too awful because you can instantiate an rng of your own 
> and use it in just the same way - but if you do this in clojure, bang goes 
> your rand-nth. Yes, the problem is one you can easily solve with a few 
> minutes coding. But an api should gently lure into doing things the right way 
> rather than wrong one - so wouldn't it be a good idea to add change the 
> standard api to include a function that takes a seed? A random that allows 
> you to see the last "seed" would be even better. That way when you get
> 
> => (foo-uses-rand "bar')
> ..crazy result *sometimes*
> 
> then
> 
> => (def wrong (get-last-rand-seed))
> 
> would give you the seed needed to repeat the last call to any random fn. So 
> you could fix your code and verify by re-seeding with "wrong" and repeating 
> the function call.
> 
> To me this seems a nice low-impact solution. It wouldn't make repeatability 
> bullet proof, but I'd suggest it would be an easily implemented mild 
> improvement for a future version of clojure.
> 

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