The first thing to know is that (most) data structures in clojure are immutable, and most functions are functional. This means that they have no side effects. In your case, filter does not change the sequence, returns a new one containing only unfiltered elements.
So, to filter myseq you need to do something like:
(def filtered-seq (filter (fn [x] ...) myseq))
The filter will call the function again, binding x to the current filtered item in myseq . That is, for the first time it will be attached to {:name "Peter" :rank 2222} , and then to {:name "Anna" :rank 111} . filtered-seq will contain only those elements for which the function returned. myseq will not be changed!
So, you want to leave only elements with :rank above 222:
(filter (fn [x] (> (:rank x) 222)) myseq)
What is it. And another feature of the filter is that it is lazy. That is, the elements in the returned collection are "implemented" (or calculated) only when they are needed.
You do not need to use loop for this, since filter does the job nicely and loop not lazy.
However, your loop does not work as it has several problems:
recur is out of loop . In this case, clojure will return to the beginning of the function.- you need to build the return value and you need to maintain the "current" element
- you need to check the final condition correctly
The code may look something like this (untested):
(defn remove-lower [number myseq] (loop [sq myseq res []] (if (empty? sq) res (let [current (first sq)] (if (> (:rank current) number) (recur (rest sq) (conj res current)) (recur (rest sq) res))))))
Please note how:
recur now inside the loopres contains the return value, and sq contains the current left sequence- each
recur passes the new sq and res values ββfor the next iteration sq "shrinks" with each iteration, so the loop will eventually exit if myseq not infinite. Compare this with filter , which handles infinite sequences perfectly.
As you can see, this is harder to read and less general than filter , and also impatient (not lazy).