I have used the following in the past in some utils I have for seqs:

(defn take-while-reduce 
  "fancy take accumulating a reduced value on taken items
    this value can then be tested in the take fn

   e.g (take-while-reduce 0 (fn [v i] (inc v)) 
                            (fn [v i] (= v i)) 
                          [1 2 3 5 6 7])
   => (1 2 3)"
  [initial reduce-fn pred coll]
  (when-let [s (seq coll)]
    (let [[f & r] coll
          reduce-value (reduce-fn initial f)]
      (if (pred reduce-value f)
        (cons f (take-while-reduce reduce-value reduce-fn pred r))))))

(comment
  ;; examples
;; take while value increment
(take-while-reduce 0 (fn [v i] (inc v)) (fn [v i] (= v i)) [1 2 3 5 6 7])

;; acts like a line break
(take-while-reduce 0 
                   (fn [v i] (+ v (count i)))
                   (fn [v i] (< v 20)) 
                   (ccsu/partition  "the quick brown fox jumps" #"\s+"))
)

; ccsu/partition is the old clojure contrib str-utils2 - it's a while since 
I did this

Dave


On Friday, 31 August 2012 22:08:03 UTC+10, shaobohou wrote:
>
> Hi,
>
> I am trying to write a function which takes a list of strings, tokenize 
> each one, and maximise N such that the number of unique tokens in the first 
> N strings is less than 
> some number M.
>
> I have written the following function using take-while and a pred function 
> with an atom to store the set of unique tokens. It works and is just as 
> fast as a messier loop/recur version. 
>
> (defn take-as-many-as-possible-until
>   [ss tok-fn m]
>   (let [items (atom #{})]
>     (-> (fn [v]
>           (swap! items (partial apply merge) (tok-fn v))
>           (< (count @items) m))
>      (take-while ss))))
>
> However, I have noticed that the take-while documentation says that the 
> pred function should be side-effect free. Will this be problem in my 
> implementation if I am calling it from multiple threads? And what would be 
> the more idiomatic way of implementing this kind of behaviour?
>
> Thanks,
> Shaobo
>
>
>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to