How can I make a function execute another function at most N times in Clojure?
First of all, I have a Mysql table:
create table t (id int(11) PRIMARY KEY unsigned NOT NULL AUTO_INCREMENT, name varchar(20), age int(10));
I am defining a funtion that will create a string at t:
(require '[honeysql.core :as sql])
(defn do-something []
(sql/query {:insert-into :t
:values [{:name "name1" :age 10}]})
(> 3 (rand-int 5)))
And now I want to run this function until it returns true, but no more than N times.
This code is take-times
incorrect because iteration will test the function do-something
once and then structure the lazy sequence.
(defn take-times []
(some true? (repeat 5 (do-something))))
This one take-times2
will render do-something
5 times no matter what it returns do-something
.
(defn take-times2 []
(some true? (for [i (range 5)]
(do-something))))
What if I don't use recursion function and macro?
source to share
This should work:
(->> (repeatedly do-something)
(take 5)
(some true?))
Update (04.11.2014):
Since it repeatedly
actually allows the extra length parameter, this is also fine:
(some true? (repeatedly 5 do-something))
Example
(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
source to share
The shrink function has a reduced ability to stop processing a sequence based on user-defined criteria.
Using a random sequence of true and false
(defn rand-seq [] (repeatedly #(rand-nth [true false false false false])))
Use shorthand to build the vector until either a true value is found or the maximum number of false values ββis reached.
(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))
This can be verified by calling
(at-most-or-true (rand-seq) 5)
source to share