Система условий Common Lisp для передачи контроля - PullRequest
5 голосов
/ 01 июня 2010

Я сразу признаю, что следующее довольно ужасное описание того, что я хочу сделать.Извиняюсь заранее.Пожалуйста, задавайте вопросы, чтобы помочь мне объяснить.: -)

Я написал ETL (Извлечение, Преобразование, Загрузка) на других языках, которые состоят из отдельных операций, которые выглядят примерно так:

// in class CountOperation
IEnumerable<Row> Execute(IEnumerable<Row> rows) {
    var count = 0;
    foreach (var row in rows) {
        row["record number"] = count++;
        yield return row;
    }
}

Затем вы вводите число из нихоперации и вызовите Dispatcher, который отвечает за вызов операций и передачу данных между ними.

Я пытаюсь сделать что-то похожее в Common Lisp, и я хочу использовать ту же базовую структуру, т.е.каждая операция определяется как обычная функция, которая вводит список и выводит список, но лениво.

Я могу define-condition условие (have-value) использовать для yield -подобного поведения, и яможет запустить его в один цикл, и он прекрасно работает.Я определяю операции одинаково, перебирая входные данные:

(defun count-records (rows)
   (loop for count from 0
         for row in rows
         do (signal 'have-value :value `(:count ,count @,row))))

Проблема в том, что я хочу связать вместе несколько операций и запустить их.Моя первая попытка написать диспетчер для них выглядит примерно так:

(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)))

Но перезапуски имеют только динамический экстент: у каждой операции будут одинаковые имена перезапусков.Перезапуск - это не объект Lisp, который я могу сохранить для сохранения состояния функции: это то, что вы вызываете по имени (символу) внутри блока обработчика, а не продолжение, которое вы можете сохранить для дальнейшего использования.

Можно ли сделать что-то, как я хочу здесь?Или мне лучше просто заставить каждую функцию-функцию явно просматривать свою очередь ввода и явно помещать значения в очередь вывода?

Ответы [ 2 ]

3 голосов
/ 01 июня 2010

Обычный Лисп не поддерживает сопрограммы или нисходящие продолжения. Вы не можете выпрыгнуть из некоторых вычислений, а затем вернуться обратно. Существуют библиотеки (например, cl-cont ) для обеспечения некоторой поддержки продолжений.

Я бы использовал потоковые (см. SICP ) абстракции (с использованием FORCE и DELAY) или что-то вроде SERIES (которая реализует эффективные средства отложенного вычисления). *

0 голосов
/ 01 июня 2010

Я не думаю, что система условий - это то, что нужно использовать здесь. Будет лучше с продолжениями. Кроме того, компилятор C # превращает представленный вами метод в объект, подобный продолжению.

В Common Lisp вы можете создавать продолжения с помощью библиотеки cl-cont.

...