Как перевести 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)))