只是不理解用于创建上下文的运算符的宏的描述。 在我看来,如果有一个绑定,宏是唯一的选择。
这是否通过其他方式无法实现? 下面的文字到底意味着什么?
非常感谢。
除了词汇环境之外还有另一种语境。在里面 更广义的,背景是世界的状态,包括 特殊变量的值,数据结构的内容和 Lisp以外的事物。构建这种类型的运营商 上下文也必须定义为宏,除非它们的代码主体是 被封装在封闭物中。经常建立上下文宏的名称 以 - 开头。这种类型最常用的宏是 可能是打开文件。它的身体是新开的 绑定到用户提供的变量的文件:
(with-open-file (s "dump" :direction :output)
(princ 99 s))
...
这个操作符显然必须被定义为amacro,因为它绑定了s。 但是,运算符会导致在新上下文中评估表单 必须被定义为宏。
答案 0 :(得分:6)
需要在新环境中执行的表单可以通过两种方式定义:
这是不可能的:
(this-is-some-function-with-some-file-opened (princ 99))
以上是不可能的,因为princ
表单将在函数this-is-some-function-with-some-file-opened
之前执行。参数形式在被调用函数之前执行。然后,这些参数形式的值将传递给被调用的函数。
因此,对于功能版本,正文表单需要作为函数传递,稍后将使用必要的参数调用它。宏变体已经扩展为必要的形式,并将体形放在其中。
典型的宏版本:
(with-open-file (s "dump" :direction :output)
(princ 99 s))
使用函数的版本:
(call-with-open-file
(lambda (s)
(princ 99 s))
"dump"
:direction :output)
在上面作为一个函数传递身体然后跟随各种参数。从功能上看,这很好。但是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)
因此,宏代码在代码中被视为更具可读性,因为有关打开的流的所有信息都位于顶部。请注意,将函数放在最后并将其他参数放在顶部也不是一个好的选择,因为在Common Lisp lambda列表中我们有这个:位置参数首先是可选的和关键字参数。
但在许多图书馆中,我们同时获得了功能和宏。宏只是扩展到函数中。