2011-01-07 1 views
2

Ich versuche, eine externe Bibliothek in idiomatische Clojure zu wickeln. Dies beinhaltet, dass seine Datenstrukturen faul werden. Ich möchte in die statische Methode read unten kommen und FooList faul machen.Wie kann ich eine Datenstruktur innerhalb einer statischen Java-Methode erweitern, um faul zu sein?

ich in viele Probleme leite:

  1. Java statische Methoden können nicht
  2. außer Kraft gesetzt werden
  3. proxy scheint nur Instanz zu erzeugen Objekte
  4. gen-class scheint sorta Arbeit ein bisschen, aber ich bekomme in Meer verloren von Namespaces, Aliasen usw.
  5. Die fragliche Methode ruft eine andere statische und private Methode auf (die ich gerne wiederverwenden würde), wodurch das Überschreiben der öffentlichen Methode erschwert wird.

Was ist die beste Strategie, dies zu tun? Ist es möglich, FooList zu öffnen und es als faul umzusetzen, wobei die resultierende Klasse für den Rest meines Codes verfügbar ist?

org.apache.commons.collections.list.LazyList scheint für die Aufgabe geeignet, aber ich bin mir nicht sicher, wie es geht, um es tatsächlich verwenden zu können.

Hilfe?

public class Foo { 

    public static FooList read(String filename) { 
     FooList foos = new FooList(); //FooList extends ArrayList 
     BufferedReader br = new BufferedReader(new FileReader(filename)); 

     for (String s = br.readLine(); null != s; s = br.readLine()) { 
      Foo f = parseLine(s); 
      foos.add(f); 
     } 

     br.close(); 
     return foos; 
    } 

    private static Foo parseLine(String s) { 
     //return s as Foo 
    } 
} 

Antwort

1

In Clojure können Sie einfach (Seq-Sammlung) auf alle Iterable-Sammlung (z. B. Ihre FooList) aufrufen und eine Lazy-Sequenz, die die Sammlung durchläuft. Obwohl die Faulheit nicht wirklich viel gewinnt, da Sie bereits die volle FoolList auf der Java-Seite geladen haben.

Wenn Sie wirklich wollen Faulheit über beide Clojure und Java, dann könnten Sie Folgendes tun:

  • Haben Sie Ihre Java-Funktion eine benutzerdefinierte Implementierung von java.util.Iterator zurückzukehren, anstatt eine komplette Sammlung. Um zu bekommen, sollten Sie sicherstellen, dass readLine() nur einmal pro Iteration aufgerufen wird (entweder in der next() - oder hasNext() -Methode). Denken Sie daran, den Reader zu schließen, wenn Sie das Ende der Datei erreicht haben.

  • Auf der Clojure Seite schaffen die faulen f mit (Iterator-Seq java-Iterator)

Wenn Sie dies tun, dann wird die Datei in und inkrementell Reihenfolge wie die Clojure analysiert gelesen werden verbraucht wird .

+0

Danke, genau wonach ich gesucht habe. –

2

Könnte völlig außerhalb Ihres Umfangs sein, aber ich hatte eine similar problem. Also war meine letzte Wahl, mit java.lang.Iterable zu gehen, die, wenn Sie tiefer denken, die Lazynesskriterien genau passen. Ja, es hat keine Sachen List hat (z. B. size()), aber ich konnte es mir leisten, dies zur Vereinfachung zu opfern. Im Rückblick habe ich es nie bereuen, dass ich diese Wahl getroffen habe.

+0

Ich mache das gleiche ... rufen Sie einfach 'myFileIterator.next()', um die nächste Zeile zu erhalten. Wrapping der IO-Ausnahmen als RuntimeException oder als Null zurückgeben, in beide Richtungen. – dagnelies

+0

Eigentlich könnte ich, wenn ich 'FooList' affektieren könnte, einfach [clojure.lang.ISeq] implementieren (https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/ISeq .java): es würde nur bedeuten, 'first',' rest', 'more' und' cons' umzusetzen. Aber danke für eine andere Idee. –

1

Normalerweise ist dies in Java nicht sinnvoll, da Sie normalerweise die gesamte Datei lesen möchten. Wenn Sie jedoch nur den Header oder die Datei lesen möchten, die zu groß ist, um sie auf einmal zu lesen, würden Sie nur die Zeilen lesen, die Sie benötigen.

Als Übung ist es jedoch am einfachsten, diese Klasse zu ändern, indem Sie sie bearbeiten. Sie können die Quelle für diese Klasse abrufen (wenn Sie es dekompilieren müssen) und sie zuerst in Ihrem Klassenpfad hinzufügen, damit sie als Patch in Ihr aktuelles System übernommen wird.

+0

Wie ich schon sagte, portiere ich die Bibliothek in idiomatische Clojure, in der Faulheit erwünscht ist. Ich nehme an, ich könnte meine eigene gepatchte Kopie der Bibliothek beibehalten, aber ich vermute, das würde mir später mit neuen Versionen, usw. Probleme bereiten. –

+0

@Pedro, gewünscht ja, aber jede Lösung, die Sie benötigt, um eine vorhandene Bibliothek zu hacken, ist wahrscheinlich schlechter. Die beste Lösung ist, die Anbieter der Bibliothek zu bitten, sie zu ändern. –

0

Sie können Bar und BarList nicht mit den Methoden und der Lazy-Funktion, die Sie entwerfen möchten, erstellen, indem Sie an Foo und FooList delegieren und dann einfach Bar und BarList ??

Habe ich den Punkt in Ihrer Frage übersehen?

+0

Ich bin auf der Suche nach Affe Patch die Klasse in Frage, keinen Entwickler Zugriff auf die externe Bibliothek, noch meine Patch-Version des Codes beibehalten möchten. –