Опытные функции get-first, get-next и waddle от Schemer
(define get-first
(lambda (l)
(call-with-current-continuation
(lambda (here)
(set! leave here)
(waddle l)
(leave (quote ()))))))
(define get-first
(lambda (l)
(call-with-current-continuation
(lambda (here)
(set! leave here)
(leave (waddle l))))))
Для тех, кто не знаком с книгой "Закаленный интриган", get-first
, get-next
, а также waddle
(последние два не определены здесь) являются процедурами, по-видимому, для моделирования сопрограмм для итерации по дереву, переданному в waddle
что дает только листья. Просто до waddle
При втором и последнем повторном входе он устанавливает точку повторного входа туда, где он будет только когда-либо возвращать чистое значение. '()
то есть вместо того, чтобы уступать '()
, фактическая стоимость waddle
является '()
Как будто это была чистая функция с самого начала.
Имея это в виду, мы можем увидеть, что get-first
устанавливает... Когда waddle
возвращает "по-настоящему", он будет внутри call/cc
в get-first
а потом (leave (quote ()))
это значение get-first
(и, в свою очередь, это leave
предназначен для возвращения к get-next
на последней итерации, поэтому это get-next
что делает "фактическое" возвращение '()
).
Так почему же вторая версия не эквивалентна, где waddle
ценность '()
был бы аргумент leave
?
1 ответ
Путаница в том, чтоleave
"это не та функция, которой я хочу, а функция, которую он оценивает при оценке, которая выглядит слева направо и, следовательно, раньше"waddle
". Это означает, что он оценивает то, к чему он был только что установлен в предыдущем заявлении.
Мораль: будьте осторожны при использовании функций, которые подлежат переопределению в вызове функции! Если бы это было на переводчике справа налево, waddle
будет оцениваться до символа leave
была рассмотрена как функция, которая "уходит" куда угодно, в течение этого времени она будет установлена на РАЗЛИЧНУЮ функцию.