只是不明白用于创建上下文的运算符的宏的描述.在我看来,如果有一个绑定,宏是唯一的选择.
这是不是通过其他方式实现的?下面的文字到底意味着什么?
非常感谢.
除了词汇环境之外还有另一种语境.从更广泛的意义上讲,上下文是世界的状态,包括特殊变量的值,数据结构的内容以及Lisp之外的事物状态.构建这种上下文的操作符也必须定义为宏,除非它们的代码体要打包在闭包中.上下文构建宏的名称通常以 - 开头.这种类型最常用的宏可能是open-file.使用绑定到用户提供的变量的新打开文件评估其正文:
(with-open-file (s "dump" :direction :output)
(princ 99 s))
Run Code Online (Sandbox Code Playgroud)
......
这个操作符显然必须被定义为amacro,因为它绑定了s.但是,无论如何,必须将导致在新上下文中评估表单的运算符定义为宏.
需要在新环境中执行的表单可以通过两种方式定义:
什么不可能是这样的:
(this-is-some-function-with-some-file-opened (princ 99))
Run Code Online (Sandbox Code Playgroud)
以上是不可能的,因为princ表单将在函数之前执行this-is-some-function-with-some-file-opened.参数形式在被调用函数之前执行.然后,这些参数形式的值将传递给被调用的函数.
因此,对于功能版本,正文表单需要作为函数传递,稍后将使用必要的参数调用该函数.宏变体已经扩展为必要的形式,并将体形放在其中.
典型的宏版本:
(with-open-file (s "dump" :direction :output)
(princ 99 s))
Run Code Online (Sandbox Code Playgroud)
使用函数的版本:
(call-with-open-file
(lambda (s)
(princ 99 s))
"dump"
:direction :output)
Run Code Online (Sandbox Code Playgroud)
在上面,作为函数在身体中传递,然后遵循各种参数.从功能上看,这很好.但是Common Lisp在语言标准中没有这个功能.Common Lisp中提供的构建块(OPEN,CLOSE,UNWIND-PROTECT)和宏WITH-OPEN-FILE,其扩展到使用的构建块的代码.
缺点是身体可能很长,然后参数在底部:
(call-with-open-file
(lambda (s)
(princ 99 s)
; 100 more lines here
)
"dump"
:direction :output)
Run Code Online (Sandbox Code Playgroud)
因此,宏版本在代码中被视为更具可读性,因为关于打开的流的所有信息都位于顶部.请注意,将函数放在最后并将其他参数放在顶部也不是一个好的选择,因为在Common Lisp lambda列表中我们有:首先是位置参数,然后是可选和关键字参数.
但是在许多库中,人们同时获得了函数和宏.宏只是扩展到函数中.