42 votes

Clojure paresseux séquence d'utilisation

Je vais avoir du mal à comprendre comment on crée un paresseux séquence en Clojure.

La documentation pour la macro n'est pas du tout clair pour moi:

Utilisation: (lazy-seq & corps) Prend un corps, des expressions qui renvoie un ISeq ou nul, et les rendements un Seqable objet qui appelle le corps seulement la première fois seq est appelé, et va mettre en cache le résultat et de le retourner sur tous les suivants seq appels.

Tous les exemples que j'ai vu, semblent faire quelque chose comme ce qui suit:

; return everything in the sequence starting at idx n
(defn myseq-after-n [n]
  (...)
)

(def my-lazy-seq
  (lazy-seq (conj [init-value] (myseq-after-n 2)))
)

Donc, la première chose que je ne comprends pas est, depuis paresseux-seq est à l'extérieur de l'appel à cheval, comment elle fait pour prévenir les conj de générer une séquence infinie de l'évaluation?

Ma deuxième question est, est-ce paresseux de la séquence de définitions de toujours prendre cette forme générale?

56voto

mikera Points 63056

Un paresseux-seq appel juste exécute le corps une fois que la première fois qu'il est téléchargé, puis les caches et renvoie le même résultat à chaque fois qu'elle est convoquée à nouveau dans l'avenir.

Si vous voulez l'utiliser pour construire une (ou même infini) des séquences, alors vous avez besoin de manière récursive nid d'autres paresseux-seq appels dans la séquence retournée. Voici sur le cas le plus simple je pense:

(defn ints-from [n]
  (cons n (lazy-seq (ints-from (inc n)))))

(take 10 (ints-from 7))
=> (7 8 9 10 11 12 13 14 15 16)

Tout (ints-à partir de n) appel produit une séquence commençant par n, suivie d'un paresseux séquence de (ints-de inc (n)). C'est une liste infinie, mais ce n'est pas un problème car le paresseux-seq assure que (int-de inc (n)) seulement qui est appelé lorsque c'est nécessaire. Vous pouvez essayer exactement le même code sans le paresseux-seq et vous obtenez un StackOverflowError très rapidement.

paresseux-seq est juste l'une des nombreuses façons de créer des paresseux séquences, et il n'est souvent pas la plus pratique. Les éléments suivants sont quelques-uns des autres intéressants/utiles façons de créer des paresseux séquences:

; range is an easy way to get an infinite lazy sequence of integers, starting with zero     
(take 10 (range))
=> (0 1 2 3 4 5 6 7 8 9)

; map produces lazy sequences, so the following is lazy 
(take 10 (map #(* % %) (range)))
=> (0 1 4 9 16 25 36 49 64 81)

; iterate is a good way of making infinite sequenes of the form x, f(x), f(f(x))..... 
(take 10 (iterate (partial * 2) 1))
=> (1 2 4 8 16 32 64 128 256 512)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X