Zeigerzyklen in clojure

8

Ich schreibe ein Clojure-Programm, das XML analysiert. Als Teil davon möchte ich einen Baum der Knoten im XML-Dokument basierend auf der clojure.xml / parse-Funktion erstellen. Ich möchte jedoch, dass der Baum bidirektional ist - das heißt, jeder Knoten hat eine Liste von Kindern und einen Zeiger auf seinen Eltern. Es gibt nur ein Problem: Alle Daten sind unveränderlich und daher kann ich keinen Zeiger zum Eltern hinzufügen, ohne das Kind zu ändern, wodurch der Zeiger des Elternteils nutzlos wird.

Ich habe diese Antwort gefunden: Wie kann man zyklische (und unveränderliche) Datenstrukturen in Clojure ohne zusätzliche Indirektion erstellen?

Die vorgeschlagene Lösung scheint eine separate Indexkarte zu erstellen, die sich auf die Objekte im Inneren bezieht. Dies scheint eine riesige Menge Arbeit für eine viel schlechtere Lösung zu sein. Ich hätte kein Problem damit, dass der Baum während der Konstruktion veränderbar ist, aber ich kann nicht herausfinden, wie es gemacht werden kann. Gibt es wirklich keine Möglichkeit, einen zyklischen Zeiger in clojure zu bekommen?

Danke!

    
Gilthans 14.02.2012, 10:41
quelle

3 Antworten

5

Es ist logisch unmöglich, reine unveränderliche Strukturen zyklisch zu machen, da Sie durch Hinzufügen eines Eltern- oder Kindzeigers die Struktur mutieren würden.

Es gibt einen Hack, der funktioniert, obwohl ich mir nicht sicher bin, ob ich ihn empfehlen würde: Sie können Atome in Clojure-Datenstrukturen einfügen und diese dann mutieren, um die notwendigen Links zu erstellen. z.B.

%Vor%

Dies ist in vielerlei Hinsicht unangenehm:

  • Es wird dazu führen, dass Ihre REPL einen Überlauf stapelt, wenn Sie versuchen, eine davon zu drucken, weil die REPL keine zyklischen Datenstrukturen erwartet.
  • Es ist veränderbar, also verlieren Sie alle Wartbarkeits- und Parallelitätsvorteile von unveränderlichen Datenstrukturen (was eines der schönsten Dinge an Clojure ist!)
  • Sie müssen eine vollständige Kopie eines Knotens erstellen, wenn Sie ihn duplizieren möchten (z. B. beim Erstellen eines neuen XML-Dokuments), da es sich nicht mehr um einen unveränderlichen Wert handelt.
  • Die Dereferenzierung aller Atome kann beim Navigieren durch die Struktur unübersichtlich werden.
  • Sie werden Leute verwirren, die an idiomatische Clojure gewöhnt sind.

Also, es ist möglich, wenn Sie es wirklich tun wollen ......... obwohl ich persönlich denke, dass Sie auf lange Sicht immer noch viel besser dran sind, wenn Sie Ihre Dokumentendarstellung richtig unveränderlich machen. Sie könnten vielleicht etwas mehr wie XPath Stil Orte im Dokument verwenden, wenn Sie die Struktur navigieren möchten.

    
mikera 14.02.2012, 11:17
quelle
2

Haben Sie daran gedacht, Reißverschlüsse zu verwenden?

Reißverschlüsse sind so konzipiert, dass sie das Arbeiten mit Baumstrukturen effektiv ermöglichen. Es beinhaltet grundlegende Operationen wie das Betrachten von Kindern und im übergeordnet eines Knotens, wobei auch leicht durch die Struktur iterieren .

Reißverschlüsse sind ziemlich allgemein und eingeschlossene Funktionen erlauben bereits, sie von XML zu verursachen. Ein Beispiel für die anderen Bibliotheken Seite bietet ein gutes erstes Bild davon, wie man mit ihnen arbeitet.

Für einen XML-Zipper sollten Sie

verwenden %Vor%

um die Anfangsstruktur zu erstellen. Wenn Sie fertig sind, rufen Sie einfach root auf, um die Endstruktur zu erhalten.

    
deterb 14.02.2012 21:21
quelle
0

So etwas könnte funktionieren:

%Vor%

Machen Sie das Protokoll nicht Teil der öffentlichen API und berühren Sie niemals das veränderbare Feld nach der Konstruktion und Sie haben grundsätzlich einen unveränderlichen Baum. Es wird schwierig sein, den Baum nach der Konstruktion zu modifizieren. YMMV.

    
kotarak 14.02.2012 11:58
quelle