Seite 1 von 1

Gibt es einen funktionalen Iterator?

Verfasst: Sonntag 7. September 2008, 09:55
von sma
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

Verfasst: Sonntag 7. September 2008, 11:12
von audax

Verfasst: Samstag 13. September 2008, 08:41
von sma
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