Kontynuacja (informatyka)
Kontynuacja (ang. continuation) – abstrakcyjny konstrukt programistyczny służący do sterowania przepływem programu. Każdy język programowania posiada kontynuacje, ponieważ jest sposób w jaki działają języki programowania, lecz tylko niektóre dają do nich bezpośredni dostęp. W skrócie można powiedzieć. że kontynuacja to następna instrukcja, która ma zostać wykonana, gdy skończy się wykonywać aktualna instrukcja. Gdy język umożliwia bezpośredni dostęp do kontynuacji, możliwy jest powrót do miejsca w którym kontynuacja została utworzona. Dzięki kontynuacjom można zaimplementować takie konstrukcje programistyczne jak wyjątki, współprogramy, czy generatory.
Przykładowym językiem programowania, który daje dostęp do kontynuacji, jest język Scheme. W tym języku kontynuacje są typem pierwszoklasowym. Według specyfikacji języka, powinny się zachowywać dokładnie tak jak funkcje[1].
W języku Scheme, aby dostać obiekt kontynuacji używa się konstrukcji call-with-current-continuation (lub skrótu call/cc). Jest to tzw. przechwycenie kontynuacji (ang. continuation capture). Mając dostęp do obiektu kontynuacji możliwy jest powrót i kontynuowanie działania programu w miejscu, w którym kontynuacja została przechwycona[2][3].
Istnieje także sposób użycia kontynuacji w językach funkcyjnych, które nie dają bezpośredniego dostępu do kontynuacji dzięki tzw. stylowi przekazywania kontynuacji (ang. Continuation-passing style). Jest to specjalny sposób pisania programów, w którym wszystkie kontynuacje są jawne, utworzone dzięki zwykłym funkcjom[4].
Przykład
[edytuj | edytuj kod]Najprostszym przykładem użycia kontynuacji jest tzw. wczesne wyjście. Język Scheme nie pojada instrukcji return znanej z innych języków programowania, ale dzięki kontynuacjom istnieje możliwość wczesnego wyjścia.
(define (find item lst)
(call-with-current-continuation
(lambda (return)
(for-each (lambda (x)
(if (equal? x item)
(return x))
(display x)
(newline))
lst))))
(let ((result (find 'x '(a b d x y z f))))
(display "wynik: ")
(display result)
(newline))
Procedura for-each iteruje po wszystkich elementach listy, natomiast funkcja find wywołuje kontynuacje return, która wychodzi z funkcji i nie kontynuuje przetwarzania kolejnych elementów listy, gdy zostanie znaleziony szukany element.
Przykład CPS
[edytuj | edytuj kod]Poniżej przykład stylu przekazywania kontynuacji w języku JavaScript:
function silnia(n, cc) {
if (n == 0) {
cc(1);
} else {
silnia(n-1, function(t0) {
cc(n * t0)
});
}
}
silnia(10, function(wynik) {
console.log(wynik); // 3628800
});
W definicji funkcji nie została użyta instrukcja return, tylko kontynuacja w formie funkcji przekazana jako drugi argument.
Przypisy
[edytuj | edytuj kod]- ↑ First-Class Continuations (CS 6110). Cornell Computer Science. [dostęp 2025-04-05].
- ↑ Continuations | LIPS Scheme [online], lips.js.org [dostęp 2025-04-05] (ang.).
- ↑ Nils M. Holm: Sketchy LISP. 2009, s. 123-133. [dostęp 2025-04-05].
- ↑ William Clinger, The scheme environment: continuations, „ACM SIGPLAN Lisp Pointers”, 1 (2), 1987, s. 22–28, DOI: 10.1145/1317193.1317197, ISSN 1045-3563 [dostęp 2025-04-05] (ang.).