Je vais admettre dès le départ que ce qui suit est une description assez terrible de ce que je veux faire. Excuses d'avance. S'il vous plaît poser des questions pour m'aider à expliquer. :-)Commun système de condition Lisp pour le transfert de contrôle
J'ai écrit (extrait ETL, Transform, Load) dans d'autres langues qui consistent en des opérations individuelles qui ont l'air quelque chose comme:
// in class CountOperation
IEnumerable<Row> Execute(IEnumerable<Row> rows) {
var count = 0;
foreach (var row in rows) {
row["record number"] = count++;
yield return row;
}
}
Ensuite, vous chaîne un certain nombre de ces opérations ensemble, et appelez The Dispatcher, qui est responsable de l'appel des opérations et de la transmission de données entre elles. J'essaie de faire quelque chose de similaire dans Common Lisp, et je veux utiliser la même structure de base, c'est-à-dire que chaque opération est définie comme une fonction normale qui introduit une liste et sort une liste, mais paresseusement.
Je peux define-condition
une condition (have-value
) à utiliser pour yield
-comme le comportement, et je peux l'exécuter en une seule boucle, et cela fonctionne très bien. Je suis en train de définir les opérations de la même manière, une boucle à travers les entrées:
(defun count-records (rows)
(loop for count from 0
for row in rows
do (signal 'have-value :value `(:count ,count @,row))))
Le problème est si je veux enchaîner plusieurs opérations, et de les exécuter. Ma première tentative d'écriture d'un répartiteur pour ces ressemble à quelque chose comme:
(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)))
Mais redémarre ont seulement l'étendue dynamique: chaque opération aura les mêmes noms de redémarrage. Le redémarrage n'est pas un objet Lisp que je peux stocker, pour stocker l'état d'une fonction: c'est quelque chose que vous appelez par nom (symbole) dans le bloc gestionnaire, pas une continuation que vous pouvez stocker pour une utilisation ultérieure.
Est-il possible de faire quelque chose comme je veux ici? Ou est-ce que je ferais mieux de faire en sorte que chaque fonction d'opération regarde explicitement sa file d'attente d'entrée, et place explicitement les valeurs dans la file d'attente de sortie?