Wie kann ich Clojure des Chunking Verhalten für faulen ASTA vermeiden, dass ich kurzzuschließen will?

StackOverflow https://stackoverflow.com/questions/3407876

Frage

habe ich eine lange, faul Folge, dass ich faul zu reduzieren und zu testen will. Sobald zwei aufeinanderfolgende Elemente nicht = (oder ein anderes Prädikat) zueinander sind, möchte ich die Liste stoppen raubend, was zu produzieren ist teuer. Ja, das klingt wie take-while, aber lesen Sie weiter.

wollte ich etwas schreiben, einfach und elegant wie folgt aus (vorgibt, für eine Minute, dass every? wie reduce funktioniert):

(every? = (range 100000000))

Aber das funktioniert nicht faul und so hängt es auf unendlich ASTA. Ich entdeckte, dass das funktioniert fast wie ich wollte:

(apply = (range 100000000))

Allerdings habe ich diese Sequenz Chunking wurde in zusätzlichen, unnötigen Elementen resultierende erstellt und getestet. Zumindest ist es das, was ich denke, das ist das, was in dem folgende Stück Code passiert:

;; Displays chunking behavior in groups of four on my system and prints 1 2 3 4
(apply = (map #(do (println %) %) (iterate inc 1)))

;; This prints 0 to 31
(apply = (map #(do (println %) %) (range)))

fand ich eine Abhilfe mit take-while und count die Anzahl der Elemente genommen zu überprüfen, aber das ist ziemlich umständlich.

Should Ich schlage vor, höflich Rich Hickey, dass er eine Kombination aus reduce und every? Kurzschluss richtig machen, oder bin ich einige offensichtliche Art und Weise fehlt, dass bereits vorhanden ist?

EDIT:? Zwei freundliche Menschen geschrieben Lösungen zur Vermeidung von auf den faulen Sequenzen Chunking, aber wie kann ich vermeiden Chunking wenn die apply tun, der raubend in chunked Gruppen von vier zu sein scheint

EDIT # 2: Wie Stuart Sierra Notizen und ich entdeckte, unabhängig, ist dies nicht eigentlich Chunking. Es gilt nur normal wirkt, so dass ich diese geschlossenen nennen würde und ihm die Antwort geben. Ich bin mit einer kleinen Funktion in einer separaten Antwort des reduce'ing Teil des Problems zu tun, für diejenigen, die interessiert sind.

War es hilfreich?

Lösung

KORRIGIERT ZWEIMAL: Ein einfacher Weg, um un-Chunk einer faule Sequenz:

(defn unchunk [s]
  (when (seq s)
    (lazy-seq
      (cons (first s)
            (unchunk (next s))))))

Erste Version weggelassen (when ... so dass es eine unendliche seq von Null ist, nachdem die Eingangssequenz beendet zurückgegeben.

Zweite Version verwendet first statt seq, damit es auf Null gestoppt.

RE: Ihre andere Frage, "Wie vermeide ich Chunking, wenn dabei die Anwendung, der raubend in chunked Gruppen von vier zu sein scheint" :

Dies ist aufgrund der Definition von =, die, wenn eine Folge von Argumenten gegeben, Kräfte der erste 4:

(defn =
  ;; ... other arities ...
  ([x y & more]
   (if (= x y)
     (if (next more)
       (recur y (first more) (next more))
       (= y (first more)))
     false)))

Andere Tipps

Suchen Sie in clojure.core bei der Definition der Anwendung macht es offensichtlich, warum es wurde in Gruppen von vier Chunking wenn apply mit einer unendlichen Folge verwendet wird. Reduce nicht Kurzschluss, entweder ... so verließ ich bin meine eigene Lösung zu schreiben:

(defn reducep
  "Like reduce, but for use with a predicate. Short-circuits on first false."
  ([p coll]
     (if-let [s (seq coll)]
       (reducep p (first s) (next s))
       (p)))
  ([p val coll]
     (if-let [s (seq coll)]
       (if-let [v (p val (first s))]
         (recur p (first s) (next s))
         false)
       true)))

Dann Stuart unchunk mit (mit einem zusätzlichen and)

(defn unchunk [s]
  (lazy-seq
   (cons (first s)
         (and (next s)
              (unchunk (next s))))))

ich:

(reducep = (map #(do (print %) %) (unchunk (range)))) ;; Prints 01, returns false
(reducep = (map #(do (print %) %) (repeat 20 1))) ;; returns true
(reducep = (map #(do (print %) %) (unchunk [0 0 2 4 5]))) ;; Returns false
(reducep = (map #(do (print %) %) (unchunk [2 2 2 2 2]))) ;; returns true

Wenn das funktioniert auch für Sie, mod diese nach oben.

Bearbeiten : Stuart modifizierte Version von unchunk nach seiner Bearbeitung ist wahrscheinlich besser, die man in dieser früheren Post.

fand ich diesen Beitrag, während eine Frist an einem 4clojure Problem trifft und ich fand einen anderen Weg, um die 32-Brocken zu vermeiden:

;; add another dummy sequence parameter to the map:
(apply = (map #(do (prn %2) %) (range) (range)))

Die höheren arity Formen der Karte erscheinen nicht gestückelt Sequenzen zu verwenden (clojure 1.5)

Sie haben etwas mit dem zweiten Parameter zu tun, also Wesen Formulieren das könnte besser sein:

(apply = (map (fn [i _] (prn i) i) (range) (range)))

Dies ist nicht so sauber wie die anderen Lösungen aber könnte gut sein für quick and dirty Anwendungen, wie die Prüfung „wegen Chunking dieses langsam?“.

In Bezug auf apply, könnten Sie partition bekommen Paare aus der Sequenz und = sie verwenden:

(every? #(apply = %) (partition 2 1
    (map (fn [i _] (prn i) i) (range) (range))))

Obwohl reducep sieht auch nützlich.

PS. Ich möchte nicht den Eindruck erwecken, dass die segmentierte Sequenz ist langsamer, ist es nicht. Mein Problem ist, dass der 4clojure Testfall „zunächst“ auf meiner seq Erzeugungsfunktion ruft über ein Bereich von Werten, so Mittel Chunking ich 32-mal die Arbeit machen. (PPS. Mein Code ist immer noch zu langsam)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top