Lisp动态范围:一个强大的简短例子推理吗?

时间:2012-05-31 11:31:12

标签: dynamic scope lisp

无处不在,大师们说:“动态范围可以比词汇范围更强大。”,但直到现在我还没有看到一个让我信服的简洁例子。

2 个答案:

答案 0 :(得分:3)

我最喜欢的例子在Emacs论文中得到了很好的解释:http://www.gnu.org/software/emacs/emacs-paper.html#SEC17

  

动态范围很有用。考虑功能编辑图片,即   用于暂时稍微改变某些编辑命令,以便   它们更方便编辑排列的文本   二维图片。例如,更改打印字符   替换现有文本而不是将其推到右侧。编辑   图片通过绑定参数变量的值来工作   动态,然后将编辑器作为子例程调用。编辑   `exit'命令导致返回Edit Picture子程序,该子程序   立即返回编辑器的外部调用。在里面   过程中,动态变量绑定是未完成的。

     

动态绑定对命令的元素特别有用   派遣表。例如,用于撰写回复的RMAIL命令   一条消息暂时定义了字符Control - Meta - Y to   将原始邮件的文本插入回复。功能   总是定义实现此命令,但Control - Meta - Y.   除了正在编辑回复时,不会调用该函数。该   reply命令通过动态绑定调度表来完成此操作   Control - Meta - Y的条目,然后将编辑器称为   子程序。当编辑器的递归调用返回时,   用户编辑的文本将作为回复发送。

     

动态范围不必是唯一的范围规则   提供,只是有用它。

答案 1 :(得分:3)

多年前,当我使用Clipper5语言(原始DBIII编程语言的扩展实现)时,我习惯了动态范围。

如果使用正确,动态范围非常有用,因为它允许在调用链中传递参数,而不需要使中间函数必须知道它们。 这样可以很容易地在所需位置添加例如新参数(即参数的来源和使用参数的位置。

假设您有“关闭订单”,称为“打印发货文档”,称为“打印发票”,称为“打印发票行”。如果您需要添加一个会影响发票行打印方式的新参数,您只需在顶级“关闭顺序”功能中添加用户选项,使用此值设置动态变量并仅处理该值在“print-invoice-row”中。

函数接口链将保持与该参数“干净”,仅列出要传递的基本数据。

这与使用全局变量类似,但它“完成正确”,因为它在调用后不会保持“脏”,并且在大多数支持线程的实现中,它甚至可以从多个线程中使用而没有问题(每个线程都会有它自己的价值观。)

我在过去发现使用这种方法对“配置”值非常有帮助的能力。但是你必须注意避免不必要的名字冲突。

另一个好用的例子是Common Lisp中的*standard-output*,即一个你需要存储在全局中的值(比如C语言)或另一个显然不切实际的替代方法是传递它对于可能需要它的每个函数(要么直接使用它,要么调用可能需要它的函数)。

使*standard-output*成为动态变量允许Common Lisp程序避免在任何地方引用它仍然保持在需要时将标准输出重定向到其他东西的能力(并且以比C更干净的方式)。