Gibt es einen funktionalen Iterator?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Versteckt sich irgendwo eine Datenstruktur, die sich wie folgt verhält?

Ich habe einen Text, den ich nacheinander in Token zerteile. Immer wenn ich nach dem nächsten Token frage, soll dieser berechnet werden. Ich möchte aber beliebig wieder zurückgehen können und alte Token nochmals erfragen, ohne das sie erneut berechnet werden.

Clojure kennt mit `ISeq` einen funktionalen Iterator, der diese Anforderung erfüllt.

Hier ist eine Implementierung in Python:

Code: Alles auswählen

class Seq(object):
    def __init__(self, first, restfun):
        self.first, self.restfun, self.restval = first, restfun, self
    
    @property
    def rest(self):
        if self.restval is self:
            self.restval = self.restfun()
        return self.restval
Damit müsste ich aber alle Funktionen, die auf einer solchen `Seq` arbeiten, selbst schreiben. Das würde ich vermeiden wollen, auch wenn es eine nette Übung in funktionaler Programmierung ist. Beispielhaft sei hier nur die Funktion `take` gezeigt:

Code: Alles auswählen

def take(n, coll):
    if n > 0:
        return Seq(coll.first, lambda: take(n - 1, coll.rest))
Mit der folgenden Funktion kann etwas in Python aufzählbares zu einer `Seq` machen:

Code: Alles auswählen

def seq(sequence):
    i = iter(sequence)
    def next():
        try:
            return Seq(i.next(), next)
        except StopIteration:
            return None
    return next()
Einfach einen Generator zu benutzen funktioniert nicht, denn dieser kann den selben Wert nicht mehrfach liefern.

Stefan
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Audax, danke für den Hinweis. Den Code hatte ich mir auch angeschaut, er erfüllt aber nicht direkt meine Anforderung, jeweils ein Objekt zu haben, was das aktuelle Element (den Kopf einer Liste) unveränderlich repräsentiert. Ich müsste die LazyList nochmal in ein anderes Objekt einpacken, welches Liste und aktuellen Index kombiniert. Da kann ich dann auch bei meinem "LazyCons" beleiben, das finde ich verständlicher.

Stefan
Antworten