如何在不使用letrec
的情况下实施set!
?
在我看来,set!
是一种命令式编程结构,通过使用它,人们就失去了函数式编程的好处。
答案 0 :(得分:9)
我知道我们通常会要求复制内容,但对您的问题没有简短的答案。 http://www.cs.indiana.edu/~dyb/pubs/fixing-letrec.pdf
答案 1 :(得分:9)
没有。仅仅因为功能特性是在幕后使用命令式代码实现的,这并不能使该功能成为必需。我们的计算机器势在必行;所以在某些时候,所有功能代码都必须通过翻译成命令式代码来实现!
这里要理解的关键是:函数式编程属于接口,而不属于实现。如果代码本身无法观察任何副作用,即使副作用实际上发生在幕后,一段代码也是有用的。也就是说,如果你多次检查同一个变量的相同绑定的值,你将得到相同的值 - 即使幕后的那个值是通过set!
使用的。
在letrec
的情况下,这里有一点点:如果对letrec
中的任何绑定的评估导致另一个绑定被解除,则结果是未定义的。所以,这段代码的结果是未定义的:
(letrec ((foo bar)
(bar 7))
(cons foo bar))
letrec主体中foo
的值未定义。另一方面,定义了以下结果:
(letrec ((foo (lambda () bar))
(bar 7))
(cons (foo) bar))
这是因为评估lambda
会捕获对bar的引用,但是直到在正文中执行闭包时才会查找实际值。