2012-07-01 2 views

ответ

7

Оператор call/cc используется для вызова данной процедуры с текущим продолжением (отсюда и название call-with-current-continuation). Чтобы понять, как это работает, нам нужно знать, что такое продолжение.

В программе, в тот момент, что call/cc выполняется, продолжение выглядит следующим образом:.

CONT = (let ([x HOLE]) 
     (x (lambda (ignore) "hi"))) 

где HOLE является заполнителем для значения для подключения Другими словами, продолжение является оставшееся вычисление. Вы можете вставить значение в продолжение, если хотите прогрессировать.

Теперь call/cc фиксирует это продолжение и передает его на процедуру (lambda (k) k). Вы можете видеть, что эта процедура сразу же возвращает продолжение. Таким образом, программа сводится к:

(let ([x CONT]) 
    (x (lambda (ignore) "hi"))) 

Применение продолжения захваченного call/cc заменяет текущее вычисление с этим продолжением закупорено значением, которое вы даете ему. Таким образом, приложение (x (lambda (ignore) "hi")) превращается в:

(let ([x (lambda (ignore) "hi")]) 
    (x (lambda (ignore) "hi"))) 

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

3

В первой строке [x (call/cc (lambda (k) k))] мы создаем новое продолжение, которое связано с параметром k в принятом lambda. То, что k возвращается и, в свою очередь, связано с локальной переменной x, поэтому x является продолжением.

Во второй строке x вызывается с одним аргументом lambda; аргумент игнорируется, и результатом вызова (lambda (ignore) "hi") является "hi", который, наконец, возвращается в результате продолжения. Это эквивалентно простому вызову:

(call/cc 
(lambda (k) 
    (k "hi"))) 
1

Почему это выражение оценивается как «привет»?

(let ([x (call/cc (lambda (k) k))]) 
    (x (lambda (ignore) "hi"))) 

Первый шаг должны решить, что k выглядит следующим образом:

(define k 
    (lambda (value) 
    (let ((x value)) 
     (x (lambda (ignore) "hi"))))) 

Мы сразу видим, что это так же, как

(define k 
    (lambda (x) 
    (x (lambda (ignore) "hi")))) 

Но я не упомянул одну маленькой детали , Если k имеет значение , он как бы вызывается в положении хвоста.

Так (f (k 3)) для всех продолжений k построен call/cc является же, как (k 3). Это всегда немного сложно.

Итак, давайте использовать lambda^, чтобы означать, что функция, которую она вводит , должна вызываться так, как если бы она находилась в положении хвоста.

(define k 
    (lambda^ (x) 
    (x (lambda (ignore) "hi")))) 

Теперь мы знаем, что k, мы также должны знать, что возвращение из (call/cc (lambda (k) k)) действительно использует по умолчанию.

Это должно был быть написано правильно, как

(call/cc (lambda (k) (k k))). 

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

Мы знаем, что такое k.

Итак, мы знаем, что это должно быть таким же, как, (для удобства чтения давайте превратить x 'S в позиции аргумента в y-х гг.)

((lambda^ (x) (x (lambda (ignore) "hi"))) 
(lambda^ (y) (y (lambda (ignore) "hi")))) 

Таким образом, мы оцениваем как позиции к функциям.

После того, как мы вызываем функцию в позиции функции, мы сделали, так как он возглавляет lambda^ Таким образом, мы должны знать, что

((lambda^ (x) (x (lambda (ignore) "hi"))) 
(lambda^ (y) (y (lambda (ignore) "hi")))) 

имеет значение, заменив x

((lambda^ (y) (y (lambda (ignore) "hi"))) 
(lambda (ignore) "hi")) 

и еще один шаг, заменяющий y

ведет к

((lambda (ignore) "hi") (lambda (ignore) "hi")), который игнорирует свой аргумент и возвращает «привет»

Смежные вопросы