2014-10-30 50 views
3

的所有第一,我有一个MySQL表是这样的:如何在Clojure中最多执行N次函数?

create table t (id int(11) PRIMARY KEY unsigned NOT NULL AUTO_INCREMENT, name varchar(20), age int(10));

我定义了一个funtion将在T创建一个行:

(require '[honeysql.core :as sql]) 

(defn do-something [] 
    (sql/query {:insert-into :t 
       :values [{:name "name1" :age 10}]}) 
    (> 3 (rand-int 5))) 

现在我想运行此功能直到它返回真,但最多N次。

这个take-times代码是错误的,因为重复将一次评估do-something函数,然后构造惰性序列。

(defn take-times [] 
    (some true? (repeat 5 (do-something)))) 

take-times2将EVAL的do-something 5倍不管什么do-something回报。

(defn take-times2 [] 
    (some true? (for [i (range 5)] 
        (do-something)))) 

如果我不使用递归函数和宏,该怎么办?

回答

5

这应该工作:

(->> (repeatedly do-something) 
    (take 5) 
    (some true?)) 

更新(2014年4月11日):

由于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 
0

reduce函数根据用户定义的标准停止处理序列的选项减少。

使用的真正的随机序列和假

(defn rand-seq [] (repeatedly #(rand-nth [true false false false false]))) 

使用减少,直到真正的发现或假值的最大数量已达到建立一个向量。

(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) 
+1

这可以用一个数字累加器被简化'(FN [NV](如果(或V(> = ACC MAX-假))(减小V BE测试)(inc acc))'0作为初始条件 – noisesmith 2014-10-30 18:31:02

+0

哦,你使用的方式减少意味着truthy值永远不会返回 – noisesmith 2014-10-30 18:32:06

+0

我没有把这段代码看做有用的东西,它只是一个例子,可以重新插入sql插入等。数字累加器的第一个评论将是一个更好的例子,为此目的。 – GregA100k 2014-10-30 19:01:32