В статье Википедии о Continuation говорит:
«В любом языке, который поддерживает затворов, можно писать программы в продолжении прохождения стиля и вручную осуществить вызов/куб.см.»
Либо это правда, и мне нужно знать, как это сделать, либо это неверно, и это утверждение нужно исправить.
Если это правда, пожалуйста, покажите мне, как реализовать call/cc в Lua, потому что я не вижу, как это сделать.
Я думаю, что смогу реализовать call/cc вручную, если у Lua была функция coroutine.clone, как описано here.
Если закрытие недостаточно для реализации call/cc, то что еще нужно?call/cc в Lua - возможно?
Текст ниже является необязательным.
P.S .: Lua имеет одноразовые продолжения со своим сопрограммным столом. Функция coroutine.clone позволила бы мне клонировать ее, чтобы называть ее несколько раз, тем самым эффективно делая вызов/cc возможным (если я неправильно понимаю call/cc). Однако эта функция клонирования не существует в Lua. Кто-то из канала IRA Lua предложил использовать библиотеку Pluto (она реализует сериализацию), чтобы маршалить сопрограмму, скопировать ее, а затем отключить ее и снова использовать. Хотя это, вероятно, будет работать, меня больше интересует теоретическая реализация call/cc и в поиске того, что является фактическим минимальным набором функций, которые должен иметь язык, чтобы обеспечить его ручную реализацию.
EDIT 1: Ok люди, помогите мне здесь, это заняло у меня много времени, потому что я не знаю ни одной схемы, но я придумал что-то, что должно помочь нам. Пожалуйста, ознакомьтесь с приведенными ниже кодами. Первая - это программа на Схеме, вторая - та же самая программа, но в Lua.
Надеюсь, это поможет нам. Я считаю, что мы очень близко.
P.S .: Эти примеры взяты из первого примера на the Wikipedia article on CallCC. Схема версия
(define call/cc call-with-current-continuation)
; callcc CPS-transformed (thanks to the people from the #scheme channel at freenode.net)
(define cpscallcc
(lambda (consumer k)
(let ((cc (lambda (result) (k result))))
(consumer cc k))))
; this is the continuation we will use to display the "returned" values
(define main-continuation
(lambda (result)
(display "--> ")
(display result)
(newline)))
; define f function non-CPS
(define (f return)
(return 2)
3)
; these are my past attempts at defining a CPS f function
;(define (cps-f return k)
; (k (return 2)) 3)
;(define (cps-f return k)
; (k (lambda()
; (return 2)
; 3)))
; this is what I came up with - I'm not sure if this is correctly CPS-transformed but I believe so
(define (cps-f return k)
(return 2)
(k 3))
; call the non-CPS f function
(display (f (lambda (x) x))) ; displays 3
(newline)
; call the non-CPS f function with call/cc (I don't understand what this does)
(display (call/cc f)) ; displays 2
(newline)
; now call the CPS version of the f function
(cps-f (lambda (x) x) main-continuation) ; displays --> 3
; now call the CPS version of the f function with the CPS version of call/cc
(cpscallcc cps-f main-continuation) ; displays --> 2 but then it also displays --> 3 afterwards -> I'm not sure why it displays the 3 afterwards, as it should only display the 2 just like the non-CPS versions above
Lua версия
-- callcc CPS-version
cpscallcc = function(consumer, k)
local cc = function(result)
return k(result) -- ?or k(result)
end
return consumer(cc, k) -- ?or return consumer(cc,k)
end
-- define f function non-CPS
f = function(ret)
ret(2)
return 3
end
-- define f function CPS-version (again, not sure this is correct)
cps_f = function(ret, k)
ret(2)
k(3)
end
-- call the non-CPS f function
print(f(function(x) return x end))
-- we cant call the non-CPS f function with callcc because
-- Lua doesnt have callcc, but the line below displays the correct expected output (maybe by accident)
--cpscallcc(f, print)
-- now call the CPS version of the f function
cps_f(function(x) return x end, print) -- displays 3
; now call the CPS version of the f function with the CPS version of call/cc
cpscallcc(cps_f, print) -- displays 2 and then 3 just like the Scheme version!!
-- so apparently the translation from Scheme to Lua is correct...
Я использую DrScheme и Lua для Windows - для тех, кто хочет помочь вверх из тех, являются два легко загружать и устанавливать инструменты, которые просто работают.
Вау, ты меня очень близко понимаешь. Можете ли вы расширить определение функции callcc? Особенно, объясняя часть, которая позволяет ему запомнить сохранение/запоминание всех состояний, таких как вызов/cc схемы. – PeterM
У меня возникли проблемы с тем, как можно использовать эту функцию callcc - на Схеме вам нужно установить место для вызова/cc, чтобы перейти на нее, но в CPS вы не ... это отбрасывает меня, я думаю. – PeterM
Так как k - это замыкание, которое callcc вернется, передав его аргументу f выполнит задание call/cc [я только что редактировал мое определение выше, так как я забыл вернуться правильно]. Это тривиально, когда программа находится в CPS, потому что продолжение всегда доступно; в Схеме его скрытые, а работа call/cc сложнее (на уровне языка реализация может быть столь же тривиальной в компиляторе), поскольку она должна «реактивировать» продолжение. –