Ich gebe zu, dass das Folgende eine ziemlich schreckliche Beschreibung dessen ist, was ich tun möchte. Entschuldigung im Voraus. Bitte stellen Sie Fragen, um mir zu erklären. :-)Common Lisp Condition System für die Übertragung der Kontrolle
ich geschrieben habe ETLs (Extract, Transform, Load) in anderen Sprachen, die von einzelnen Operationen bestehen, die wie etwas aussehen:
// in class CountOperation
IEnumerable<Row> Execute(IEnumerable<Row> rows) {
var count = 0;
foreach (var row in rows) {
row["record number"] = count++;
yield return row;
}
}
Dazu Zeichenfolge eine Anzahl dieser Operationen zusammen, und Rufen Sie den Dispatcher auf, der für den Aufruf von Operationen und das Übertragen von Daten zwischen ihnen zuständig ist.
Ich versuche etwas ähnliches in Common Lisp zu tun, und ich möchte die gleiche Grundstruktur verwenden, d. H. Jede Operation ist wie eine normale Funktion definiert, die eine Liste eingibt und eine Liste ausgibt, aber träge.
Ich kann define-condition
eine Bedingung (have-value
) für yield
-ähnliches Verhalten zu verwenden, und ich kann es in einer einzigen Schleife laufen, und es funktioniert super. Ich bin die Definition der Operationen die gleiche Art und Weise, durch die Eingänge Looping:
(defun count-records (rows)
(loop for count from 0
for row in rows
do (signal 'have-value :value `(:count ,count @,row))))
Das Problem ist, wenn ich aneinanderzureihen mehrere Operationen möchten, und führen Sie sie. Mein erster Versuch, einen Dispatcher für diese Schreiben sieht ungefähr so aus:
(let ((next-op ...)) ;; pick an op from the set of all ops
(loop
(handler-bind
((have-value (...))) ;; records output from operation
(setq next-op ...) ;; pick a new next-op
(call next-op)))
aber neu gestartet haben nur dynamischen Umfang: jeder Betrieb die gleichen Neustart Namen hat. Der Neustart ist kein Lisp-Objekt, das ich speichern kann, um den Status einer Funktion zu speichern: Es ist etwas, was Sie im Handler-Block mit dem Namen (Symbol) aufrufen, nicht eine Fortsetzung, die Sie für die spätere Verwendung speichern können.
Ist es möglich, hier etwas zu tun, was ich will? Oder bin ich besser dran, wenn ich einfach jede Operationsfunktion explizit auf ihre Eingabewarteschlange schaue und explizit Werte in die Ausgabewarteschlange lege?