La prima cosa da sapere è che (la maggior parte) le strutture di dati in clojure sono immutabili e la maggior parte delle funzioni sono, beh, funzionale. Ciò significa che non hanno effetti collaterali. Nel tuo caso filter
non cambia la sequenza in alcun modo, ne restituisce una nuova, contenente solo gli elementi non filtrati.
Così, per filtrare myseq
è necessario fare qualcosa di simile:
(def filtered-seq (filter (fn [x] ...) myseq))
Filtro chiamerà la funzione più volte, vincolante x
alla voce attualmente filtrato in myseq
. Cioè, la prima volta sarà legato a {:name "Peter" :rank 2222}
, quindi a {:name "Anna" :rank 111}
. filtered-seq
conterrà solo gli elementi, per i quali la funzione ha restituito true. myseq
sarà non da modificare!
Quindi, si vuole lasciare solo gli elementi con :rank
superiore a 222:
(filter (fn [x] (> (:rank x) 222)) myseq)
Questo è tutto. E un'altra cosa sul filtro è che è pigro. Cioè, gli articoli nella collezione restituita sono "realizzati" (o calcolati) solo quando sono necessari.
Non è necessario utilizzare loop
per questo, come filter
funziona correttamente, e loop
non è pigro.
Detto questo, il vostro loop
non funziona perché ha diversi problemi:
recur
è al di fuori del loop
. In questo caso il clojure tornerà all'inizio della funzione.
- è necessario costruire un valore di ritorno ed è necessario mantenere l'elemento "corrente"
- è necessario controllare correttamente per la condizione di fine
Il codice potrebbe essere simile a questa (non testata):
(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))))))
si noti come:
recur
è ora all'interno del loop
res
contiene il valore di ritorno e sq
contiene la sequenza attualmente sinistra
- ogni
recur
passa i nuovi valori di sq
e res
per la prossima iterazione
sq
è "a contrazione" ad ogni iterazione, cosicché il ciclo si casualmente uscita a meno che myseq
sia infinito. Contrasto a filter
, che gestisce perfettamente sequenze infinite.
Come si vede questo è più difficile da leggere e meno generale di filter
ed è anche desideroso (non pigro).
Ancora meglio! Ecco come ho provato a farlo prima ma non ci sono riusciti. Grazie. –
'(filtro # (> (: rank%) 220) myseq)' – Ankur
Grazie mille ragazzi, il codice ora funziona e anche molto veloce! –