Warum können Bereiche nicht für die Funktionalität der Pipes-Bibliothek verwendet werden?

10

Jonathan Boccara (Autor von Fluent C ++ ) hat eine Bibliothek namens Pipes geschrieben .

Diese "Piping", so die Hauptseite des Repositorys, ähnelt nicht der Verwendung von Bereichen, obwohl sie gleich aussieht: Sie basiert nicht auf faulem Ziehen, sondern auf eifrigem Drücken. Es wird jedoch angegeben, dass man die Bereichsbibliothek nicht verwenden kann, um verschiedene 'Pipe'-Operationen auszuführen. Zum Beispiel:

  • entpacken - Nehmen Sie eine komprimierte Eingabe - im Wesentlichen eine Reihe von k-Tupeln - und erzeugen Sie k separate, unabhängige Ausgaben.
  • Gabel - Erstellen Sie mehrere (unabhängige) Kopien eines Containers / Bereichs.

Ich verstehe nicht ganz, warum das im Prinzip der Fall ist. (Natürlich mit Ausnahme von Bereichen, in denen Sie den Enditerator / Sentinel nicht erhalten können.)

einpoklum
quelle

Antworten:

7

Was diskutiert wird, ist im Wesentlichen der Unterschied zwischen einer Push-basierten Verarbeitungsmethode und einer Pull-basierten Verarbeitungsmethode. In einem Push-System wie dieser Pipes-Bibliothek erstellen Sie eine Verarbeitungskette, und jeder Verarbeitungsschritt überträgt seine Daten direkt in den nächsten. In einem Pull-System-ähnlichen Bereich erstellen Sie eine Darstellung von Daten, auf die Sie zugreifen und die Sie nach Bedarf ändern können. Die Verarbeitung erfolgt nicht von alleine. Dies geschieht nur, wenn jemand versucht, die Reichweite zu nutzen.

Die Operationen unzipund forksind beide Eins-zu-Viele-Operationen: Sie nehmen eine einzelne Eingabe und ordnen sie vielen Verarbeitungsoperationen zu.

Als Push-System kann die Pipes-Bibliothek aufgrund der Struktur ihrer API Eins-zu-Viele-Operationen ausführen. Eine Operation wird durch einen Funktionsaufruf dargestellt. Die Eingabe wird durch den Verwendungsort impliziert (Verwendung >>=oder Weitergabe an einen Prozessor). Die Parameter der Funktion definieren ihre Ausgabe (ignorieren Parameter, die für den Prozessor selbst bestimmt sind). Und da C ++ - Funktionen eine beliebige Anzahl von Parametern haben können, fällt natürlich eine Eins-zu-Viele-Zuordnungsoperation aus. Sie liefern einfach geeignete Prozessoren für die verschiedenen Ausgänge.

Als Pull-System basieren Bereiche auf Rückgabewerten. C ++ hat keinen Sprachmechanismus für die Rückgabe mehrerer Werte. Das Beste, was wir tun können, ist, einen "Wert" zurückzugeben, der mehrere Werte darstellt.

Die Verkettung von Bereichsadaptern basiert jedoch letztendlich darauf, dass die Eingaben Bereiche sind . Und ein "Wert", der mehrere Werte darstellt, ist selbst kein Bereich. Es kann Bereiche enthalten, aber das macht es nicht zu einem Bereich.

Jetzt müssen Sie diesen definitiv "kein Bereich" -Typ verwenden und alle Ihre Bereichsadapter damit arbeiten lassen. Durch Anwenden eines Bereichsadapters muss dieser Vorgang typübergreifend übertragen werden, wodurch ein Viele-zu-Viele-Vorgang erstellt wird. Das zu tun ist nicht einfach.

Aber was noch wichtiger ist ... das ist wahrscheinlich nicht das, was Sie wollen . Wenn Sie forkeinen Bereich haben, möchten Sie mit ziemlicher Sicherheit eine andere Verarbeitung für die replizierten Bereiche durchführen. Und das schließt jede Möglichkeit, die |Operation dazu zu verwenden, vollständig aus . Sie müssen Möglichkeiten entwickeln, um Adapter auf bestimmte Teile dieser Bereichstupel anzuwenden. Und diese Wege werden zunehmend wie ein Push-basierter Prozessor aussehen.

Letztendlich hat ein Pull-Style-System nur einen Ausgang auf jeder Ebene. Dies ist nur ein Teil des Kernkonzepts einer solchen API: Jeder Verarbeitungsschritt generiert einen Bereich. Dies hat seine Vorteile (verzögerte Verarbeitung), aber die Darstellung von Eins-zu-Viele-Operationen ist eine seiner Schwachstellen.

Bereiche können sicherlich eine unzipFunktion haben ( forkkopiert wirklich nur den Bereich). Aber es wäre kein |Stiladapter; Es wäre eine Funktion, die einen Bereich über einen zerlegbaren Typ nimmt und ein Tupel von Bereichen zurückgibt. Wenn Sie mehr mit ihnen verarbeiten möchten, müssen Sie das Tupel in einem Wert speichern, auf die einzelnen Elemente zugreifen und sie nach Belieben verwenden.

Nicol Bolas
quelle