Kontynuacja (ang. continuation) – abstrakcyjny konstrukt programistyczny służący do sterowania przepływem programu. Każdy język programowania posiada kontynuacje, ponieważ tak właśnie 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.

Jednym z języków programowania, który daje bezpośredni 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 pozyskać 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

Najprostszym przykładem użycia kontynuacji może być nieskończona pętla:

(let ()
  (define k (call/cc (lambda (cc) cc)))
  (display "Wikipedia")
  (newline)
  (k k))

W tym przykładzie tworzymy pusty zasięg i wewnątrz przypisujemy do zmiennej k kontynuacje. Gdy wywołamy kontynuację, kod przeskoczy do miejsca, w którym zostaje przypisana wartość do zmiennej k. Gdy przekażemy (k 10), zostanie wywołane (define k 10), ponieważ w tym momencie kontynuacja została przypisana do zmiennej k. Natomiast, gdy wywołamy (k k), program przeskoczy na górę i wywoła (define k k) (przy czym pierwsze k to identyfikator a drugie to wartość kontynuacji). Dzięki temu mamy nieskończoną pętlę.

Innym przykładem może być tzw. wczesne wyjście (ang. early return). 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 kontynuację return, która wychodzi z funkcji i nie kontynuuje przetwarzania kolejnych elementów listy, gdy zostanie znaleziony szukany element.

Kontynuacje w połączeniu z makrami umożliwiają tworzenie nowych konstrukcji programistycznych[5].

Przykład CPS

edytuj

Poniżej znajduje się przykład wykorzystywania 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 sterująca return, tylko kontynuacja w formie funkcji przekazana jako drugi argument.

Przypisy

edytuj
  1. First-Class Continuations (CS 6110). Cornell Computer Science. [dostęp 2025-04-05].
  2. Continuations | LIPS Scheme [online], lips.js.org [dostęp 2025-04-05] (ang.).
  3. Nils M. Holm: Sketchy LISP. 2009, s. 123-133. [dostęp 2025-04-05].
  4. William Clinger, The scheme environment: continuations, „ACM SIGPLAN Lisp Pointers”, 1 (2), 1987, s. 22–28, DOI10.1145/1317193.1317197, ISSN 1045-3563 [dostęp 2025-04-05] (ang.).
  5. 5.6. Continuations. W: R. Kent Dybvig: The Scheme Programming Language, fourth edition. MIT Press, 2009. ISBN 0-262-51298-X. (ang.).

Linki zewnętrzne

edytuj
  • Continuations [online], lips.js.org [dostęp 2026-06-02] (ang.).

📚 Artikel Terkait di Wikipedia

MiRNA

[dostęp 2024-10-09] . Ahmed M.A.M. Abdelaal Ahmed M.A.M. i inni, A first-in-class fully modified version of miR-34a with outstanding stability, activity

Funkcja anonimowa

immediately-invoked function expression) dobrze to ilustrują: (function(){ ... }()) i (function(){ ... })() Skracając zapis „function(){ ... }” przez f

Długa pamięć krótkotrwała

initialize = function(input_size, hidden_size, output_size) { self$lstm <- nn_lstm( input_size = input_size, hidden_size = hidden_size, batch_first = TRUE )

Prototype JavaScript Framework

Metoda Class.Create() jest używana do stworzenia klasy. var FirstClass = Class.create( { // Metoda initialize oznacza konstruktor initialize: function ()

C++11

zrozumienie ich własności: function<int ( int, int )> pF ; // Tworzenie adaptera przy użyciu // klasy szablonowej 'function'. plus<int> add ; // 'plus'

Lista skrótów i skrótowców używanych w informatyce

Interface FEXT – Far End Crosstalk FFT – Fast Fourier Transformation FIFO – First In First Out FLAC – Free Lossless Audio Codec FLOPS – FLoating-Point Operation

Amfetamina

NestlerN. EJ NestlerN., HymanH. SE HymanH., Chapter 13: Higher Cognitive Function and Behavioral Control, [w:] SydorS. A, BrownB. RY (red.), Molecular Neuropharmacology:

Klasterowy ból głowy

Headache: Evidence for a Disorder of Circadian Rhythm and Hypothalamic Function, „Canadian Journal of Neurological Sciences”, 29 (1), 2002, s. 33–40, DOI: 10