【发布时间】:2019-06-25 22:35:22
【问题描述】:
我希望这不是在打死马,但我想就编写引用透明代码的另一种可能策略发表意见。 (之前关于引用透明度的讨论在Using a Closure instead of a Global Variable)。同样,目标是消除大多数全局变量,但保留它们的便利性,而不会将容易出错的引用或潜在的非功能性行为(即,引用不透明、副作用和不可重复的评估)注入代码中。
建议是使用局部特殊变量来建立初始绑定,然后可以动态地将其传递给最终使用它们的后续嵌套函数。与全局变量一样,预期的优点是不需要将局部特殊变量作为参数传递给所有中间函数(其功能与局部特殊变量无关)。但是,为了保持引用透明性,它们将作为参数传递给最终消费者函数。
我想知道的是,浮动大量动态变量是否容易出现编程错误。对我来说,这似乎不是特别容易出错,因为以前绑定的变量的任何本地重新绑定都不应影响原始绑定,一旦它被释放:
(defun main ()
(let ((x 0))
(declare (special x))
(fum)))
(defun fum ()
(let ((x 1)) ;inadvertant? use of x
(setf x 2))
(foo))
(defun foo ()
(declare (special x))
(bar x))
(defun bar (arg) ;final consumer of x
arg)
(main) => 0
这个策略有问题吗?
【问题讨论】:
-
你去恢复多年的 Common Lisp 开发(特殊变量把你的大脑变成布丁),然后你退缩并定义一个接受参数的函数?为什么要这么做?你的目标不是避免传递争论吗? 现在说真的 - 这个策略有问题吗? - 是的,很多,调试ie是一场噩梦。
-
TL;DR; 是的。
-
我试图指出局部特殊变量和引用透明度不一定不兼容。如果您的嵌套函数在引用上是透明的,那么您可以可靠地自下而上地测试它们,一次一个。没有复杂的调试,只需对每个都进行良好的简单测试。
-
仅仅因为你的代码没有修改全局变量,并不意味着它是引用透明的。简而言之,这意味着函数只对自己的参数进行操作。你所做的恰恰相反。请不要通过阅读 On Lisp 的部分内容来开始学习 Lisp。从 Common Lisp:符号计算简介 开始。 On Lisp 绝不是教程。
-
@davypough 你应该看到 Doug Hoyte 的 Let Over Lambda 部分,pandoric macros in chapter 6 做你想做的事。我用一个例子编辑了我的答案。
标签: dynamic global-variables common-lisp