关于OnLisp中描述的宏用法

use*_*328 4 lisp common-lisp

只是不明白用于创建上下文的运算符的宏的描述.在我看来,如果有一个绑定,宏是唯一的选择.

这是不是通过其他方式实现的?下面的文字到底意味着什么?

非常感谢.

除了词汇环境之外还有另一种语境.从更广泛的意义上讲,上下文是世界的状态,包括特殊变量的值,数据结构的内容以及Lisp之外的事物状态.构建这种上下文的操作符也必须定义为宏,除非它们的代码体要打包在闭包中.上下文构建宏的名称通常以 - 开头.这种类型最常用的宏可能是open-file.使用绑定到用户提供的变量的新打开文件评估其正文:

(with-open-file (s "dump" :direction :output)
  (princ 99 s))
Run Code Online (Sandbox Code Playgroud)

......

这个操作符显然必须被定义为amacro,因为它绑定了s.但是,无论如何,必须将导致在新上下文中评估表单的运算符定义为宏.

Rai*_*wig 6

需要在新环境中执行的表单可以通过两种方式定义:

  • 一个宏,它扩展到环境的准备和形式的身体
  • 一个函数,它接受一个在里面执行的函数

什么不可能是这样的:

(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列表中我们有:首先是位置参数,然后是可选和关键字参数.

但是在许多库中,人们同时获得了函数和宏.宏只是扩展到函数中.