Как реализовать продолжения?

Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  1. Вызов метода экземпляра объекта null.
  2. Доступ или изменение поля объекта null.
  3. Принимая длину null, как если бы это был массив.
  4. Доступ или изменение слотов null, как если бы это был массив.
  5. Бросок null как будто это было значение Throwable.

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

Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html

53
задан Óscar López 30 October 2011 в 04:18
поделиться

10 ответов

Я не забываю читать статью, которая может помочь Вам: Чейни на M.T.A. :-)

Некоторые реализации Схемы, которую я знаю, такой как SISC, выделяют свои кадры вызова на "куче".

@ollie: Вы не должны делать подъема, если все Ваши кадры вызова находятся на "куче". Существует компромисс в производительности, конечно: время для подъема, по сравнению с издержками, требуемыми выделить все кадры на "куче". Возможно, это должен быть настраиваемый параметр периода выполнения в интерпретаторе.:-P

18
ответ дан Chris Jester-Young 7 November 2019 в 08:35
поделиться

Хорошая сводка доступна в Стратегии реализации Первоклассных Продолжений , статья Clinger, Hartheimer и Ost. Я рекомендую смотреть на реализацию Схемы Chez в частности.

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

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

28
ответ дан Chris Jester-Young 7 November 2019 в 08:35
поделиться

Если Вы запускаете с нуля, действительно необходимо заглянуть к преобразованию Стиля передачи продолжения (CPS).

Хорошие источники включают "LISP в маленькие части" и Схема Marc Feeley в представлении 90 минут .

13
ответ дан Will Ness 7 November 2019 в 08:35
поделиться

Примеры, на которые можно посмотреть: Курица (реализация Схемы, записанная в C та поддержка продолжения); Paul Graham На Lisp - где он создает преобразователь CPS для реализации подмножества продолжений в языке Common LISP; и Weblocks - основанная на продолжении веб-платформа, которая также реализует ограниченную форму продолжений в языке Common LISP.

7
ответ дан Kyle Burton 7 November 2019 в 08:35
поделиться

Традиционный путь состоит в том, чтобы использовать setjmp и longjmp, хотя существуют протесты.

Вот довольно хорошее объяснение

7
ответ дан Will Ness 7 November 2019 в 08:35
поделиться

Используйте явный стек вместо этого.

1
ответ дан Patrick 7 November 2019 в 08:35
поделиться

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

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

1
ответ дан olliej 7 November 2019 в 08:35
поделиться

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

Наилучший текущий подход к отображению стека спагетти схемы в стек - использование трамплинов: по сути, дополнительная инфраструктура для обработки не-C -как звонки и выходы из процедур. См. Батутный стиль (ps) .

Есть код , иллюстрирующий обе эти идеи.

7
ответ дан 7 November 2019 в 08:35
поделиться

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

Прерывания тривиально реализуются с помощью волокон. http://en.wikipedia.org/wiki/Fiber_%28computer_science%29 . Единственное, что требует тщательной инкапсуляции, это передача и возврат значений параметров.

В Windows оптоволокно выполняется с помощью семейства вызовов CreateFiber/SwitchToFiber. В Posix-совместимых системах это можно сделать с помощью makecontext/swapcontext.

boost::coroutine имеет рабочую реализацию coroutines для C++, которая может служить ориентиром для реализации.

.
5
ответ дан 7 November 2019 в 08:35
поделиться

Помимо хороших ответов, которые вы уже получили, я рекомендую книгу Эндрю Аппеля Compiling with Continuations. Она очень хорошо написана и, хотя не имеет прямого отношения к C, является источником действительно хороших идей для авторов компиляторов.

В Chicken Wiki также есть страницы, которые вы найдете очень интересными, например, внутренняя структура и процесс компиляции (где CPS объясняется на реальном примере компиляции).

8
ответ дан 7 November 2019 в 08:35
поделиться
Другие вопросы по тегам:

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