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?

+3


source to share


2 answers


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

      

+5


source


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)

      

0


source







All Articles