我刚刚开始学习Clojure,并且试图模拟Monty Hall问题:
(defn create-contest
"Creates a monty hall doors contest"
[n]
(do (def door-with-car (rand-int n))
(map
(fn [i] (if (= i door-with-car) :car :closed))
(range n))))
(defn create-doors
"Create a collection of monty hall contests"
[doors contests]
(doall
(map
(fn [i] (create-contest i))
(repeat contests doors))))
但是每次我执行create-doors
功能时,所有装有轿厢的车门最终都处在相同的位置:
broker.core> (create-doors 4 10)
((:car :closed :closed :closed)
(:car :closed :closed :closed)
(:car :closed :closed :closed)
(:car :closed :closed :closed)
(:car :closed :closed :closed)
(:car :closed :closed :closed)
(:car :closed :closed :closed)
(:car :closed :closed :closed)
(:car :closed :closed :closed)
(:car :closed :closed :closed))
broker.core> (create-doors 4 10)
((:closed :car :closed :closed)
(:closed :car :closed :closed)
(:closed :car :closed :closed)
(:closed :car :closed :closed)
(:closed :car :closed :closed)
(:closed :car :closed :closed)
(:closed :car :closed :closed)
(:closed :car :closed :closed)
(:closed :car :closed :closed)
(:closed :car :closed :closed))
broker.core> (create-doors 4 10)
((:closed :car :closed :closed)
(:closed :car :closed :closed)
(:closed :car :closed :closed)
(:closed :car :closed :closed)
(:closed :car :closed :closed)
(:closed :car :closed :closed)
(:closed :car :closed :closed)
(:closed :car :closed :closed)
(:closed :car :closed :closed)
(:closed :car :closed :closed))
我在做什么错了?
答案 0 :(得分:6)
您非常接近,您应该在这里使用let
而不是def
形式:
(defn create-contest
"Creates a monty hall doors contest"
[n]
(let [door-with-car (rand-int n)] ;; let instead of def
(map
(fn [i] (if (= i door-with-car) :car :closed))
(range n))))
def
会将一些值绑定到当前名称空间中的var,但是您想在此函数的范围内绑定一个值,这就是let
的优点。另请参见this Q&A。
(defn create-doors
"Create a collection of monty hall contests"
[doors contests]
(map
create-contest ;; no need to wrap create-contest in another function here
(repeat contests doors)))
您不需要将create-contest
包装在另一个与map
一起使用的函数中-您只需将函数作为值直接传递给map
即可。 doall
仅用于强制实现map
中的惰性序列,因此您可能不需要/想要在create-doors
中使用它。
(create-doors 4 10)
=>
((:closed :closed :car :closed)
(:closed :closed :closed :car)
(:closed :car :closed :closed)
(:closed :closed :closed :car)
(:closed :car :closed :closed)
(:closed :car :closed :closed)
(:closed :car :closed :closed)
(:closed :closed :closed :car)
(:closed :closed :car :closed)
(:closed :closed :car :closed))
答案 1 :(得分:1)
从@TaylorWood's solution开始,您可以更简洁地表示两个函数,尽管我不确定简洁版本是否清晰。
您的create-contest
的{{1}}函数对每个数字map
进行测试,以查看它是否是那个。最好直接更改一个。为此,我们需要一个向量,我认为您在模拟游戏时仍要查找该向量:
i
您的 (defn create-contest [n]
(assoc (vec (repeat n :closed)) (rand-int n) :car))
函数反复将相同的参数传递给其create-doors
的函数。您可以在闭包上使用repeatedly
以获得相同的效果:
map
或
(defn create-doors [doors contests]
(repeatedly contests (partial create-contest doors)))