2014-10-30 49 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