2010-05-31 16 views
5

Przyznam, że poniżej jest dość okropny opis tego, co chcę zrobić. Przeprosiny z góry. Proszę zadać pytania, które pomogą mi wyjaśnić. :-)Powszechny system warunkowy Lispa do przeniesienia kontroli

mam napisane ETLs (ETL) w innych językach, które składają się z poszczególnych operacji, które wyglądają mniej więcej tak:

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

Wtedy ciąg liczba tych operacji razem i call The Dispatcher, który odpowiada za wywoływanie operacji i przesuwanie danych między nimi.

Próbuję zrobić coś podobnego w Common Lisp, i chcę użyć tej samej podstawowej struktury, tj. Każda operacja jest zdefiniowana jako normalna funkcja, która wprowadza listę i wyświetla listę, ale leniwie.

Mogę define-condition stan (have-value) do stosowania w przypadku zachowania podobnego do yield i mogę uruchomić go w pojedynczej pętli, i działa świetnie. Jestem definiowanie operacji w ten sam sposób, zapętlenie poprzez wejść:

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

Problem jest, jeśli chcę ciąg razem kilka operacji i uruchomić je. Moja pierwsza próba pisania dyspozytora dla nich wyglądał:

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

Ale restartuje mieć tylko dynamiczny zakres: każda operacja będzie mieć takie same nazwy restart. Ponowne uruchomienie nie jest obiektem Lisp, który można przechowywać, do przechowywania stanu funkcji: jest to coś, co wywołujesz po nazwie (symbolu) wewnątrz bloku obsługi, a nie kontynuację, którą możesz przechowywać do późniejszego wykorzystania.

Czy można zrobić coś takiego, jak chcę tutaj? A może lepiej po prostu sprawić, by każda funkcja operacyjna jawnie spoglądała na swoją kolejkę wejściową i jawnie umieszczała wartości w kolejce wyjściowej?

Odpowiedz

0

Nie sądzę, że ten system warunkowy jest tutaj właściwy. Będzie lepiej z kontynuacjami. Ponadto kompilator C# zmienia prezentowaną metodę w obiekt podobny do kontynuacji.

W Common Lisp można tworzyć kontynuacje z biblioteką cl-cont.

3

Plain Common Lisp nie obsługuje coroutines ani kontynuacji w dół. Nie można wyskoczyć z niektórych obliczeń, a następnie wskoczyć z powrotem. Istnieją biblioteki (na przykład cl-cont), które zapewniają "pewne" wsparcie dla kontynuacji.

Używałbym abstrakcji "strumieniowych" (patrz SICP) (używając FORCE i DELAY) lub czegoś w rodzaju SERIES (która implementuje wydajne narzędzie do leniwego obliczania).