J'ai essayé ce qui suit dans Clojure, en m'attendant à ce que la classe d'une séquence non paresseuse soit renvoyée:
(.getClass (doall (take 3 (repeatedly rand))))
Cependant, cela revient toujours clojure.lang.LazySeq
. Je suppose que doall
cela évalue la séquence entière, mais renvoie la séquence d'origine car elle est toujours utile pour la mémorisation.
Alors, quel est le moyen idiomatique de créer une séquence non paresseuse à partir d'une séquence paresseuse?
clojure
lazy-evaluation
Tim Clemons
la source
la source
doall
(vec (take 3 (repeatedly rand)))
Réponses:
doall
est tout ce dont vous avez besoin. Ce n'est pas parce que leseq
type aLazySeq
est en attente d'évaluation. Lazy met enseq
cache leurs résultats, donc tout ce que vous avez à faire est de marcherseq
une fois sur le paresseux (comme ledoall
fait) afin de tout forcer, et ainsi le rendre non paresseux.seq
ne force pas l'évaluation de la collection entière.la source
realized?
.realize
opération correspondanterealized?
.contains?
ne se soucient pas de savoir si vous avez réalisé le seq paresseux ou non, cela répond à la question spécifique telle que posée, mais moins au titre de la question.C'est dans une certaine mesure une question de taxonomie. une séquence paresseuse n'est qu'un type de séquence, tout comme une liste, un vecteur ou une carte. Donc, la réponse est bien sûr "cela dépend du type de séquence non paresseux que vous souhaitez obtenir: faites
votre choix parmi:
(doall ... )
(apply list (my-lazy-seq)) OR (into () ...)
(vec (my-lazy-seq))
Vous pouvez avoir n'importe quel type de séquence qui répond à vos besoins.
la source
(vec (my-lazy-seq))
n'est pas si agréable dans des situations comme celles-ci:(vec (json/parse-string "{\"foo\":\"bar\"}")) ;; => [["foo" "bar"]]
Depuischeshire
choisit de produire un lazy-seq de(json/parse-string)
(json/parse-string-strict)
Ce type riche semble connaître son clojure et a tout à fait raison.
Mais je pense que cet extrait de code, en utilisant votre exemple, pourrait être un complément utile à cette question:
En effet le type n'a pas changé mais la réalisation a
la source
realized?
revenirtrue
. Par exemple(let [r (range) r? (realized? r)] (doall (take 1 r)) [r? (realized? r)]) => [false true]
[true true]
Je suis tombé sur ce billet de blog sur le fait de
doall
ne pas être récursif. Pour cela, j'ai trouvé que le premier commentaire dans le post faisait l'affaire. Quelque chose du genre:J'ai trouvé cela utile dans un test unitaire où je voulais forcer l'évaluation de certaines applications imbriquées
map
pour forcer une condition d'erreur.la source
la source