2 Stimmen

lazy-seq für rekursive Funktion

Entschuldigung für den vagen Titel, ich schätze, ich verstehe mein Problem einfach noch nicht gut genug, um es zu fragen, aber es geht los. Ich möchte eine rekursive Funktion schreiben, die eine Reihe von Funktionen auswertet und sich dann selbst mit deren Ergebnissen aufruft usw. Die Rekursion hört bei einer Funktion auf, die eine Zahl zurückgibt.

Ich möchte jedoch, dass die Funktion f, die an einem beliebigen Punkt in der Rekursion ausgewertet wird, in eine Funktion s verpackt wird, die beim ersten Mal, wenn sie ausgewertet wird, einen Anfangswert (z. B. 0 oder das Ergebnis einer anderen Funktion i) zurückgibt, gefolgt von dem Ergebnis der Auswertung von f (so dass sie beim nächsten Mal, wenn sie ausgewertet wird, das zuvor ausgewertete Ergebnis zurückgibt und den nächsten Wert berechnet). Das Ziel ist es, die Rekursion zu entkoppeln, so dass sie fortgesetzt werden kann, ohne dass es zu diese .

Ich glaube, ich verlange einen Lazy-Seq. Es ist ein Rohr, das sich an einem Ende mit Auswertungen einer Funktion füllt, und am anderen Ende kommen historische Ergebnisse heraus.

3voto

Alex Miller Punkte 67243

Ihre Beschreibung erinnert mich ein wenig an Ermäßigungen ? Reduktionen führen eine Reduktion durch und geben alle Zwischenergebnisse zurück.

user> (reductions + (range 10))
(0 1 3 6 10 15 21 28 36 45)

Hier (Bereich 10) erzeugt eine Folge von 0 bis 9. Reductions wendet + wiederholt an, wobei das vorherige Ergebnis von + und das nächste Element in der Folge übergeben werden. Alle Zwischenergebnisse werden zurückgegeben. Es könnte aufschlussreich sein, sich die Quelle der Kürzungen.

Wenn Sie einen Test (Prüfung auf Wert) in diese, das ist einfach zu tun, mit einem if in Ihrer Funktion (obwohl es nicht stoppen Traversieren der seq) bauen müssen. Wenn Sie eine Bedingung vorzeitig beenden wollen, müssen Sie Ihre eigene Schleife/Recur schreiben, was amalloy bereits gut gemacht hat.

Ich sage es nur ungern, aber ich vermute, dass dies auch ein Fall für die Staatsmonade sein könnte, aber IANAMG (I Am Not A Monad Guy).

0voto

amalloy Punkte 82950

Ich verstehe Ihr Ziel nicht ganz: Viele der von Ihnen verwendeten Begriffe sind vage. Was meinen Sie z. B. damit, dass Sie eine Folge von Funktionen auswerten und dann auf deren Ergebnisse zurückgreifen wollen? Diese Funktionen müssen dann wohl No-Arg-Funktionen (Thunks) sein, nehme ich an? Aber einen Thunk zu haben, der zuerst x zurückgibt und dann beim nächsten Aufruf y zurückgibt, ist ziemlich abscheulich und zustandsorientiert. Vielleicht Trampolin einen Teil Ihres Problems lösen wird?

Sie haben auch auf etwas verlinkt, das Sie vermeiden wollen, aber Sie scheinen den falschen Link eingefügt zu haben - es ist nur ein Link zurück zu dieser Seite. Wenn das, was Sie vermeiden wollen, ein Stack-Überlauf ist, dann ist Trampolin wahrscheinlich ein guter Weg, um das zu erreichen, obwohl es auch mit loop/recur möglich sein sollte. Diese Vorstellung, dass Thunks x zurückgeben, wenn sie nicht y zurückgeben, ist Wahnsinn wenn die Vermeidung von Stapelüberläufen Ihr Hauptziel ist. Tun Sie das nicht.

Ich habe eine Vermutung über das plausibelste Endziel angestellt, das Sie haben könnten, und hier ist meine Umsetzung:

(defn call-until-number [& fs]
  (let [numeric (fn [x] (when (number? x) x))]
    (loop [fs fs]
      (let [result (map #(%) fs)]
        (or (some numeric result)
            (recur result))))))

(call-until-number (fn [] (fn [] 1))) ; yields 1
(call-until-number (fn [] (fn [] 1))  ; yields 2
                   (fn [] 2))
(call-until-number (fn f [] f)) ; never returns, no overflow

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X