Wenn ich in Clojure eine Funktion memoize, nenne sie f
und rufe sie in einem Argument a
auf.
Wenn a
ein großer Lazy-Wert ist, gibt memoize einen Wert basierend auf dem Thunk-Vergleich zurück, anstatt die Auswertung von a
zu erzwingen und das Ergebnis zu vergleichen?
Wo ein Thunk der unbewertete Teil der Lazy-Sequenz ist.
Wenn dies nicht der Fall ist, gibt es eine eingebaute Möglichkeit, dieses Verhalten zu erhalten?
Danke!
Wie von mikera angegeben, verarbeitet memoize
keine unendlichen Lazy Seqs. Ich füge diese Antwort hinzu, um eine kurze Beschreibung der Implementierungsgründe dafür zu geben (plus zwei Ideen für identitätsbasierte Memo-Schemata, eine einfache, eine komplexe). (Bearbeiten: Tatsächlich gibt es eine einfache allgemeine identitätsbasierte Lösung, siehe unten.)
memoize
verwendet eine Hash-Map zum Speichern der Zuordnung von Argumenten zu Werten und Hash-Maps verwenden clojure.lang.Util/hasheq
, wenn festgestellt wird, ob ein Objekt einer ihrer Schlüssel ist (außer leere Maps, die nur false
zurückgeben). Da die Implementierung von hasheq
für Lazy Seqs die Gesamtheit der Seqs erzwingt, fragt jede Map, ob eine unendliche Lazy Seq eine ihrer Schlüssel ist, dass sie in eine unendliche, Speicher erschöpfende Schleife geht. Das gleiche gilt für memoize
.
Eigentlich ist die Karte zunächst eine Array-Map. (In Clojure sind kleine Maps aus Gründen der Effizienz in der Regel Array-Maps. Wenn genügend Elemente in einer Array-Map enthalten sind, wird der Rückgabewert zu einer Hash-Map.) Nicht leeres Array hingegen auch kann aus einem ähnlichen Grund, der eine Äquivalenzprüfmethode betrifft, keine unendlichen Lazy Seqs verarbeiten.
assoc
gibt den Wert zurück, den System/identityHashCode
für ein bestimmtes Objekt zurückgeben würde, wenn es die Standardimplementierung verwendet (unabhängig davon, ob hashCode
überschrieben wird oder nicht).
Jetzt können Sie das tun (was mit dem normalen hashCode
nicht funktionieren würde):
Ursprüngliche Diskussion alternativer Implementierungen folgt.
Ich glaube nicht, dass es eine integrierte Lösung gibt, die Zeigergleichheit verwendet. Um eine so allgemeine wie memoize
zu implementieren, müssten Sie eine Map-Struktur mit Zeiger-Gleichheit-basierten Hashing implementieren (viz.% Co_de%). Oder Sie könnten einen einfachen "zuletzt verwendeten" Cache mit memoize
erstellen.
Memoize wird auf der Basis des Werts von jedem Argument, das Sie übergeben, Memoize.
Daher funktioniert memoize gut mit Lazy-Sequenzen als Argumente : da es den Wert der Sequenz betrachtet, wird es bei Bedarf erzwingen .
Dies bedeutet jedoch, dass Sie keine unendlichen Lazy-Sequenzen verwenden können , da die Verwendung von memoize die Auswertung dieser Variablen erzwingen kann, was eindeutig nicht gut enden wird.
Tags und Links clojure lazy-evaluation memoization