Scheme 两个方案之间的差异”;无限循环的制造者;?

Scheme 两个方案之间的差异”;无限循环的制造者;?,scheme,Scheme,在教程中 达雷尔·弗格森和德怀特·德乌戈,2001年9月 使用call/cc的“打破潜在无限循环”模式用以下方案代码进行了说明(稍作修改,在repl.it中运行,并在下面进行了注释): 第1部分:“无穷化器”在(尾部递归)循环中无限地运行“动作函数” (定义无穷大) (lambda(动作功能) “loop”是一个不带参数的闭包,它调用 “操作过程”,然后调用“循环”。 ;定义之后,只需调用“循环”。 (letrec) ((循环) (lambda() (开始 …在每个操作转到此处之前要执行的代

在教程中

达雷尔·弗格森和德怀特·德乌戈,2001年9月

使用
call/cc
的“打破潜在无限循环”模式用以下方案代码进行了说明(稍作修改,在repl.it中运行,并在下面进行了注释):

第1部分:“无穷化器”在(尾部递归)循环中无限地运行“动作函数”

(定义无穷大)
(lambda(动作功能)
“loop”是一个不带参数的闭包,它调用
“操作过程”,然后调用“循环”。
;定义之后,只需调用“循环”。
(letrec)
((循环)
(lambda()
(开始
…在每个操作转到此处之前要执行的代码。。。
(动作功能)
;…每个操作后要执行的代码将转到此处。。。
(循环(()))
(循环)
第2部分:这是在顶层调用的函数,例如
(循环到4)
。它使用
接收器调用
call/cc
,该接收器围绕计数操作函数调用
无穷大函数
,该函数在达到停止标准后通过调用接收到的延续来打破无限循环:

(定义循环直到
(λ(n)
(让
((接收机)
(lambda(退出函数);退出函数将是调用时的“当前延续”
(let((计数0));计数将使用“set!”
(无穷大)
(lambda();这是action函数
(如果(=计数n);断开标准
(退出函数计数);使用退出值继续接收调用
(开始
(显示“计数为:”)
(显示计数)
(新行)
;与下一个行动职能部门沟通
;举例说明
(设置!计数(+计数1)
)))))))));接收端定义
(呼叫/抄送接收器);用上面的接收器打电话
例如:

(循环到4)
计数为:0
计数是:1
计数是:2
计数是:3
=> 4
备选部分1:似乎(此处的名称为
无穷大函数
,最初命名为
无限循环
)函数过于复杂。以下几点似乎也适用:

(定义无穷大)
(lambda(动作功能)
(开始
59424。。。
(动作功能)
每次操作后要执行的代码将转到此处。。。
(无穷大作用函数)

我不知道这两个无限化器之间有什么不同吗?

第一个版本的
无限化器更健壮。如果某个东西在运行时重新定义了<代码>无限化器> /代码>,它仍然将继续运行。第二个将在尝试递归时调用新定义

尝试以下两种定义以查看差异:

(define (action . args)
  (display "In action")
  (newline)
  (set! infinitizer action))

(infinitizer action)
然而,除了这样的病理病例外,它们应该是等效的


另一方面,重写第一个版本以使用命名let更简洁:

(define (infinitizer action-function)
  (let loop ()
    ;; ... code to execute before each action would go here ...
    (action-function)
    ;; ... code to execute after each action would go here ...
    (loop)))

我甚至都不知道“命名let”。好的@DavidTonhofer将其转换为类似于原版的
letrec
,只是使用了更方便、更简单的语法。有关更多信息,请参见repl.it: