首先,我有一个像这样的Mysql表:
create table t (id int(11) PRIMARY KEY unsigned NOT NULL AUTO_INCREMENT, name varchar(20), age int(10));
我定义了一个在t:
中创建一行的函数(require '[honeysql.core :as sql])
(defn do-something []
(sql/query {:insert-into :t
:values [{:name "name1" :age 10}]})
(> 3 (rand-int 5)))
现在我想运行这个函数,直到它返回true但最多N次。
这个take-times
代码是错误的,因为repeat会一次评估do-something
函数,然后构造惰性序列。
(defn take-times []
(some true? (repeat 5 (do-something))))
无论take-times2
返回什么,此do-something
都会评估do-something
5次。
(defn take-times2 []
(some true? (for [i (range 5)]
(do-something))))
如果我不使用递归函数和宏,我该怎么办?
答案 0 :(得分:5)
这应该有效:
(->> (repeatedly do-something)
(take 5)
(some true?))
更新(04.11.2014):
由于repeatedly
实际上允许可选的长度参数,所以这也没关系:
(some true? (repeatedly 5 do-something))
示例强>
(defn do-something
[]
;; 20% chance of true
(let [ret (rand-nth [true false false false false])]
(prn 'hello ret)
ret))
(defn run
[]
(->> (repeatedly do-something)
(take 5)
(some true?)))
(run)
;; hello false
;; hello false
;; hello true
;; => true
(run)
;; hello false
;; hello false
;; hello false
;; hello false
;; hello false
;; => nil
答案 1 :(得分:0)
reduce函数具有减少的选项,可以根据用户定义的标准停止处理序列。
使用真假的随机序列
(defn rand-seq [] (repeatedly #(rand-nth [true false false false false])))
使用reduce构建一个向量,直到找到一个true或者达到最大错误值数。
(defn at-most-or-true [s max-false]
(reduce (fn [acc v]
(if (and (not v) (< (count acc) max-false))
(conj acc v)
(reduced acc)))
[] s))
可以通过调用
来测试 (at-most-or-true (rand-seq) 5)