Как перевести shift/reset в delimcc?

Я изучаю разделы продолжения Олега и Асаи "для чайников" (http://pllab.is.ocha.ac.jp/~asai/cw2011tutorial/main-e.pdf), но вместо этого в этом документе используется формализм смещения / сброса из оперативного материала, доступного в delimcc Олега. Итак, у меня есть несколько вопросов:

Прежде всего, что такое подсказка? И почему передается в shift и другие функции? Знать, что такое subcont, было бы неплохо, но я хочу пропустить это, поскольку я просто хочу пройтись по газете. Кроме того, в чем разница между shift а также shift0 и как они соответствуют shift в газете.

Кроме того, что является reset в delimcc? Мое внутреннее чувство говорит мне, что new_prompt а также push_prompt как-то соответствуют reset, Но мне нужно кое-что прояснить и здесь.

РЕДАКТИРОВАТЬ: я смог перевести простой пример из бумаги, и моя интуиция оказалась правильной. Однако я хотел бы получить реальное объяснение различий и почему delimcc такой, какой он есть. Вот обе версии на случай, если кому-то интересно

Бумага:

reset (fun () -> 3 + shift (fun _ -> 5 * 2) - 1)

Delimcc:

let _ = let open Delimcc in
  let np = new_prompt () in
  push_prompt np (fun () -> 3 + (shift np (fun _ -> 5 * 2)) - 1)

1 ответ

Решение

Я бы порекомендовал вам прочитать начало этой статьи, которая является журнальной версией презентации Олега delimcc, Это даст вам разумное понимание delimcc это позволит вам перенести пример вашей статьи на Shift/ Reset delimccМногострочная настройка.

Две цитаты, которые могут вас заинтересовать. Первый из версии журнала, которую я указал выше:

Читатель, уже знакомый с управлением с разделителями, может рассматривать delimcc как обобщение обычного сдвига / сброса для управления разделителями произвольного числа "разновидностей". Функция new_prompt создает управляющий разделитель - или подсказку - нового, уникального аромата. Выражение push_prompt p (fun () -> e)Обобщение reset eставит контрольный разделитель p в стеке, а затем оценивает e; take_subcont p f удаляет префикс стека до ближайшего фрейма стека, отмеченного заданным p, Удаленная часть стопки с завершающим разделителем p отрезан, упакован как объект продолжения абстрактного типа subcont и передан take_subcontаргумент f, Функция push_subcont помещает удаленные кадры стека обратно в стек, возможно, в другом контексте, таким образом восстанавливая захваченное продолжение с разделителями.

Второй из документации GNU Guile

Все еще здесь? Таким образом, когда реализуется оператор управления с разделителями, как call-with-promptнужно принять два решения. Во-первых, работает ли обработчик внутри или вне приглашения? Запуск обработчика в приглашении позволяет прервать выполнение внутри обработчика, чтобы вернуться к тому же обработчику приглашения, что часто бывает полезно. Однако он предотвращает вызовы хвоста от обработчика, поэтому он менее общий.

Аналогично, вызывает ли захваченное продолжение восстановление приглашения? Опять же, мы получаем компромисс между удобством и правильными вызовами.

Эти решения фиксируются в F- операторе Феллайзена. Если ни продолжения, ни обработчики неявным образом не добавляют приглашение, оператор известен как –F–. Это случай для Guile's call-with-prompt а также abort-to-prompt,

Если и продолжение, и обработчик неявно добавляют приглашения, то оператором является + F +. shift а также reset такие операторы.

В заключение: вы правы, что зовет new_prompt чтобы получить подсказку, а затем push_prompt установить это способ получить reset, На самом деле, вам нужно всего лишь позвонить new_prompt один раз, и может всегда выдвигать к тому же глобальному приглашению и получать обычное shift/reset поведение (объявление разных подсказок только дает вам больше свободы).

В заключение, shift определяется с примитивами delimccи это то, что делается в библиотеке. shift звонки take_subcont, немедленно переустанавливает (ту же) подсказку и предоставляет пользователю функцию, которая перезапустит прерванные вычисления. shift0 делает то же самое, за исключением того, что не переустанавливает приглашение. в delimcc код:

let shift p f = take_subcont p (fun sk () ->
  push_prompt p (fun () -> (f (fun c -> 
    push_delim_subcont sk (fun () -> c)))))

let shift0 p f = take_subcont p (fun sk () ->
  f (fun c -> push_delim_subcont sk (fun () -> c)))
Другие вопросы по тегам