Я просто не получаю продолжения!

Вы можете подумать, что понимание - это внутренняя версия цикла for. По крайней мере, я сделал сначала. Но самый простой способ понять это - заметить, что вы вызовете переменную до ее определения в первой попытке. row вызывается до его определения. Логично, что вы получите ошибку.

[cell for cell in row ...]

row не определено

[cell for row in table for cell in row]

Здесь нет проблем

32
задан Kyle Cronin 2 September 2008 в 21:33
поделиться

9 ответов

Вообразите, была ли каждая строка в Вашей программе отдельной функцией. Каждый принимает, в качестве параметра, что следующая строка / функция выполняется.

Используя эту модель, можно "приостановить" выполнение в любой строке и продолжить его позже. Можно также сделать изобретательные вещи как временно транзитный участок стек выполнения, чтобы получить значение или сохранить текущий режим выполнения к базе данных для получения позже.

42
ответ дан 27 November 2019 в 20:12
поделиться

Вы, вероятно, понимаете их лучше, чем Вы думаете, что сделали.

Исключениями является пример "восходящих единственных" продолжений. Они позволяют коду в глубине души стек к призыву к обработчику исключений для указания на проблему.

пример Python:

try:
    broken_function()
except SomeException:
    # jump to here
    pass

def broken_function():
    raise SomeException() # go back up the stack
    # stuff that won't be evaluated

Генераторы являются примерами "нисходящих единственных" продолжений. Они позволяют коду повторно входить в цикл, например, создавать новую стоимость.

пример Python:

def sequence_generator(i=1):
    while True:
        yield i  # "return" this value, and come back here for the next
        i = i + 1

g = sequence_generator()
while True:
    print g.next()

В обоих случаях, они должны были быть добавлены к языку конкретно, тогда как на языке с продолжениями, программист может создать эти вещи, где они не доступны.

11
ответ дан 27 November 2019 в 20:12
поделиться

Головы, этот пример не краток, ни исключительно ясен. Это - демонстрация мощного приложения продолжений. Как VB/ASP/C# программист, Вы не можете быть знакомы с понятием системной стопки или сохраняющий состояние, таким образом, целью этого ответа является демонстрация и не объяснение.

Продолжения чрезвычайно универсальны и являются способом сохранить режим выполнения и возобновить его позже. Вот небольшой пример совместной среды многопоточности с помощью продолжений в Схеме:

(Предполагают, что операции ставят в очередь и исключают работу из очереди как ожидалось над глобальной очередью, не определенной здесь)

(define (fork)
  (display "forking\n")
  (call-with-current-continuation
   (lambda (cc)
     (enqueue (lambda ()
                (cc #f)))
     (cc #t))))

(define (context-switch)
  (display "context switching\n")
  (call-with-current-continuation
   (lambda (cc)
     (enqueue
      (lambda ()
        (cc 'nothing)))
     ((dequeue)))))

(define (end-process)
  (display "ending process\n")
  (let ((proc (dequeue)))
    (if (eq? proc 'queue-empty)
        (display "all processes terminated\n")
        (proc))))

Это обеспечивает три глагола, которые функция может использовать - ветвление, контекстное переключение и процесс конца. Операция ветвления разветвляет поток и возвращает #t в одном экземпляре и #f в другом. Переключатели эксплуатации контекстного переключения между потоками и процесс конца завершают поток.

Вот пример их использования:

(define (test-cs)
  (display "entering test\n")
  (cond
    ((fork) (cond
              ((fork) (display "process 1\n")
                      (context-switch)
                      (display "process 1 again\n"))
              (else (display "process 2\n")
                    (end-process)
                    (display "you shouldn't see this (2)"))))
    (else (cond ((fork) (display "process 3\n")
                        (display "process 3 again\n")
                        (context-switch))
                (else (display "process 4\n")))))
  (context-switch)
  (display "ending process\n")
  (end-process)
  (display "process ended (should only see this once)\n"))

вывод должен быть

entering test
forking
forking
process 1
context switching
forking
process 3
process 3 again
context switching
process 2
ending process
process 1 again
context switching
process 4
context switching
context switching
ending process
ending process
ending process
ending process
ending process
ending process
all processes terminated
process ended (should only see this once)

Те, которые изучили разветвление, и поточная обработка в классе часто даются примеры, подобные этому. Цель этого сообщения состоит в том, чтобы продемонстрировать, что с продолжениями можно достигнуть подобных результатов в единственном потоке путем сохранения и восстановления его состояния - его продолжения - вручную.

P.S. - я думаю, что помню что-то подобное этому в На Lisp, поэтому если требуется видеть профессиональный код, необходимо проверить книгу.

9
ответ дан 27 November 2019 в 20:12
поделиться

В основном продолжение является способностью к функции, чтобы остановить выполнение и затем взять назад, где это кончило позже. В C# можно сделать это использование ключевого слова урожая. Я могу вдаваться в большее количество подробностей, при необходимости но Вы хотели краткое объяснение. ;-)

4
ответ дан 27 November 2019 в 20:12
поделиться

В C# у Вас есть доступ к двум продолжениям. Один, полученный доступ до return, позволяет методу продолжиться от того, где это назвали. Другой, к которому получают доступ до throw, позволяет методу продолжиться при ближайшем соответствии catch.

Некоторые языки позволяют Вам рассматривать эти операторы как первоклассные значения, таким образом, можно присвоить им и раздать их в переменных. То, что это означает, - то, что можно спрятать значение return или throw и назвать их позже, когда Вы действительно готовы возвратить или бросить.

Continuation callback = return;
callMeLater(callback);

Это может быть удобно в большом количестве ситуаций. Один пример похож на тот выше, где Вы хотите приостановить работу, Вы делаете и возобновляете его позже, когда что-то происходит (как получение веб-запроса или чего-то).

я использую их в нескольких проектах, я продолжаю работать. В одном я использую их так, я могу приостановить программу, в то время как я ожидаю IO по сети, затем возобновляю его позже. В другом я пишу язык программирования, где я предоставляю пользовательский доступ к продолжениям поскольку значения, таким образом, они могут записать return и throw для себя - или любой другой поток управления, как while циклы - без меня бывший должный сделать это для них.

2
ответ дан 27 November 2019 в 20:12
поделиться

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

1
ответ дан 27 November 2019 в 20:12
поделиться

Продолжения имели возобновившийся интерес с веб-программированием, потому что они приятно зеркально отражают символ паузы/резюме веб-запросов. Сервер может создать продолжение, представляющее пользовательскую сессию, и возобновить, если и когда пользователь продолжает сессию.

1
ответ дан 27 November 2019 в 20:12
поделиться

Я все еще становлюсь "привыкшим" к продолжениям, но один способ думать о них, что я нахожу полезными, как абстракции понятия Счетчика команд (PC). ПК "указывает" на следующую инструкцию выполниться в памяти, но конечно что инструкция (и в значительной степени каждая инструкция) точки, неявно или явно, к инструкции, которая следует, а также к любым инструкциям, должны обслужить прерывания. (Даже Пустая команда неявно делает ПЕРЕХОД к следующей инструкции в памяти. Но если прерывание произойдет, то это будет обычно включать ПЕРЕХОД к некоторой другой инструкции в памяти.)

Каждая потенциально "живая" точка в программе в памяти, к которой управление могло бы схватить любую данную точку, является, в некотором смысле, активным продолжением. Другие точки, которые могут быть достигнуты, являются потенциально активными продолжениями, но, главное, они - продолжения, которые потенциально "вычисляются" (динамично, возможно) в результате достижения одного или нескольких в настоящее время активных продолжений.

Это кажется немного неуместным в традиционных введениях в продолжения, в которых все незаконченные потоки выполнения явно представлены как продолжения в статический код; но это принимает во внимание то, что на компьютерах общего назначения ПК указывает на последовательность инструкции, которая могла бы потенциально изменить содержание памяти, представляющей часть той последовательности инструкции, таким образом по существу создав новое (или измененный, если Вы будете), продолжение на лету, то, которое действительно не существует с активаций продолжений, предшествующих тому созданию/модификации.

, Таким образом, продолжение может быть просмотрено как высокоуровневая модель ПК, который является, почему это концептуально включает в категорию обычный вызов процедуры / возврат (так же, как древнее железо сделало вызов процедуры / возврат через ПЕРЕХОД низкого уровня, иначе GOTO, инструкции плюс запись ПК по требованию и восстановление ее по возврату), а также исключения, потоки, сопрограммы, и т.д.

Поэтому так же, как ПК указывает на вычисления для случая в "будущем", продолжение делает то же самое, но в более высоком, более - абстрактный уровень. ПК неявно отсылает к вводу данных все ячейки памяти и регистры, "связанные" с любыми значениями, в то время как продолжение представляет будущее через соответствующие языку абстракции.

, Конечно, в то время как мог бы обычно быть всего один пк на компьютер (основной процессор), существует на самом деле много "активных" объектов выхода ПК, как сослался на вышеупомянутый. Вектор прерывания содержит набор, стек набор больше, определенные регистры могли бы содержать некоторых и т.д. Они "активируются", когда их значения загружаются в аппаратные средства ПК, но продолжения являются абстракциями понятия, не ПК или их точным эквивалентом (нет никакого свойственного понятия "основного" продолжения, хотя мы часто думаем и кодируем в тех терминах для хранения вещей довольно простыми).

В сущности, продолжение является представлением, "что сделать затем при вызове", и, как таковой может быть (и, на некоторых языках и в программах передающего стиля продолжения, часто), первоклассный объект, который инстанцируют, раздают и отбрасывают точно так же, как большая часть любого другого типа данных, и во многом как то, как классический компьютер рассматривает ячейки памяти в отношении ПК - как почти взаимозаменяемый обычными целыми числами.

2
ответ дан 27 November 2019 в 20:12
поделиться

Один способ думать о продолжении как стопка процессора. То, когда Вы "вызов функции на контексте выполнения программы c" это вызывает Вашу функцию "c", и параметр передал "c", является Вашим текущим стеком со всеми Вашими автоматическими переменными на нем (представленный пока еще другая функция, назовите это "k"). Между тем процессор начинается, создавая новый стек. При вызове "k", он выполняет "возврат из подпрограммы" (РТС) инструкция относительно исходного стека, переходя, Вы въезжаете задним ходом к контексту исходного "вызова функции на контексте выполнения программы" ("вызов-cc" с этого времени) и разрешение Вашей программы продолжиться как прежде. При передаче параметра "k" затем, это становится возвращаемым значением "вызова-cc".

С точки зрения Вашего исходного стека, "вызов-cc" похож на нормальный вызов функции. С точки зрения "c" Ваш исходный стек похож на функцию, которая никогда не возвращается.

существует старая шутка о математике, который получил льва в клетке, поднявшись в клетку, блокируя ее и объявив, что себя вне клетки, в то время как все остальное (включая льва) было в ней. Продолжения немного похожи на клетку, и "c" немного похож на математика. Ваша основная программа думает, что "c" в ней, в то время как "c" полагает, что Ваша основная программа внутри "k".

можно создать произвольный поток управляющих структур с помощью продолжений. Например, можно создать библиотеку поточной обработки. "уступите" использование "звонит-cc" для помещения текущего продолжения на очередь, и затем вскакивает к тому на главе очереди. Семафор также имеет свою собственную очередь приостановленных продолжений, и поток перенесен, беря его от семафорной очереди и ставя его основной очереди.

8
ответ дан 27 November 2019 в 20:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: