Я все еще «привыкаю» к продолжениям, но один из способов думать о них, который я считаю полезным, - это абстракции концепции счетчика программ (ПК). ПК «указывает» на следующую инструкцию для выполнения в памяти, но, разумеется, эта инструкция (и почти каждая инструкция) указывает, неявно или явно, на следующую инструкцию, а также на любые инструкции, которые должны обслуживать прерывания. (Даже инструкция NOOP неявно выполняет JUMP для следующей инструкции в памяти. Но если происходит прерывание, это обычно включает JUMP для какой-либо другой инструкции в памяти.)
Каждая потенциально «живая» точка в программе в памяти, к которой может перейти элемент управления в любой заданной точке, в некотором смысле является активным продолжением. Другие точки, которые могут быть достигнуты, являются потенциально активными продолжениями, но, более конкретно, они являются продолжениями, которые потенциально «вычисляются» (возможно, динамически) в результате достижения одного или нескольких из текущих активных продолжений.
Это кажется немного неуместным в традиционных введениях к продолжениям, в которых все ожидающие потоки выполнения явно представлены как продолжения в статическом коде; но он принимает во внимание тот факт, что на компьютерах общего назначения ПК указывает на последовательность команд, которая потенциально может изменить содержимое памяти, представляющее часть этой последовательности команд, таким образом, по существу, создавая новую (или измененную, если вы будете ) продолжение на лету, которое на самом деле не существует по состоянию активаций продолжений, предшествующих этому созданию / модификации.
Таким образом, продолжение можно рассматривать как высокоуровневую модель ПК, поэтому концептуально оно включает в себя обычный вызов / возврат процедуры (так же, как древнее железо выполняло вызов / возврат процедуры через низкоуровневый JUMP, или GOTO, инструкции и т.д.). запись ПК по вызову и его восстановление по возвращении), а также исключения, потоки, сопрограммы и т. д.
Так что, как ПК указывает на вычисления, которые должны произойти в «будущем», продолжение делает то же самое, но на более высоком, более абстрактном уровне. ПК неявно ссылается на память плюс все ячейки памяти и регистрирует «привязанные» к любым значениям, в то время как продолжение представляет будущее через языковые абстракции.
Конечно, хотя обычно на один компьютер (основной процессор) может приходиться только один ПК, на самом деле существует много «активных» объектов PC-ish, как упоминалось выше. Вектор прерываний содержит группу, стек больше, некоторые регистры могут содержать некоторые и т. Д. Они «активируются», когда их значения загружаются в аппаратный ПК, но продолжения являются абстракцией концепции, а не ПК или их точным эквивалентом. (не существует присущей концепции «основного» продолжения, хотя мы часто думаем и кодируем в этих терминах, чтобы все было довольно просто).
По сути, продолжение представляет собой представление «что делать дальше при вызове», и, как таковое, может быть (а в некоторых языках и в программах с продолжением передачи часто является) первым классом объект, который создается, передается и отбрасывается точно так же, как и большинство других типов данных, и очень похож на то, как классический компьютер воспринимает области памяти по отношению к ПК - как почти взаимозаменяемые с обычными целыми числами.