最初に知っておくべきことは、(ほとんどの) clojure のデータ構造は不変であり、ほとんどの関数は機能的であるということです。つまり、副作用がないということです。あなたの場合filter、シーケンスはまったく変更されず、フィルタリングされていないアイテムのみを含む新しいシーケンスが返されます。
したがって、フィルタリングmyseqするには、次のようにする必要があります。
(def filtered-seq (filter (fn [x] ...) myseq))
Filter は関数を繰り返し呼び出し、xで現在フィルタリングされている項目にバインドしmyseqます。つまり、最初に にバインドされ{:name "Peter" :rank 2222}、次に にバインドされます{:name "Anna" :rank 111}。にはfiltered-seq、関数が true を返した要素のみが含まれます。myseq変更されません!
:rankしたがって、 222 より大きい要素のみを残す必要があります。
(filter (fn [x] (> (:rank x) 222)) myseq)
それでおしまい。filter についてもう 1 つ重要な点は、それが怠け者だということです。つまり、返されたコレクション内のアイテムは、必要な場合にのみ「実現」(または計算) されます。
仕事がうまくいくloopように、これを使用する必要はなく、怠惰ではありません。filterloop
とはいえ、いくつかの問題があるため、あなたloopは機能しません。
recurの外loopです。この場合、clojure は関数の先頭にループ バックします。
- 戻り値を構築する必要があり、「現在の」要素を維持する必要があります
- 終了条件を適切に確認する必要があります
コードは次のようになります (未テスト)。
(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))))))
方法に注意してください:
recurの中にありますloop
res戻り値をsq含み、現在残っているシーケンスを含みます
- それぞれが次の反復のためにと
recurの新しい値を渡しますsqres
sqは反復ごとに「縮小」されるため、myseqが無限でない限り、ループは最終的に終了します。これをfilter、無限シーケンスを問題なく処理する と比較してください。
ご覧のとおり、これは読みにくく、一般的ではなくfilter、熱心です (怠惰ではありません)。