我正在将一些Scheme代码转换为Common Lisp。我不知道Scheme。我知道一点Common Lisp。
首先,Scheme代码定义了一个变量(或者它是一个常量?),其值是函数的名称:
(define alert-propagator alert-propagators)
这是功能:
(define (alert-propagators propagators)
...)
然后通过引用常量来间接调用该函数:
(alert-propagator arg)
那太漂亮了。
我想知道在Common Lisp中是否也可以这样做?这是我尝试过的:首先,我定义了一个常量并将其绑定到一个函数:
(defconstant alert-propagator #'alert-propagators)
然后我定义了函数:
(defun alert-propagators (propagators)
...)
精细。
但是现在,为了间接调用函数(通过常量),我必须使用funcall:
(funcall alert-propagator arg)
我认为这种方法违背了定义常量(抽象)的整个目的。我真正想要的是能够简单地写:
(alert-propagator arg)
有没有办法在Common Lisp中实现这个目标?
答案 0 :(得分:2)
Common Lisp是一个LISP2,它意味着操作员位置的标识符和其他位置的标识符有不同的名称空间。
(defun square (x)
(* x x))
(defparameter square 10) ; unconventional, should be *square*
(square square) ; ==> 100
这不能在Scheme中完成,因为(square square)
两个square
标识符都指向完全相同的对象。它可能是一个函数(Scheme speak中的过程),它将一个函数作为参数。
您可以使用(function square)
或语法糖短格式#'square
从函数名称空间中获取对象,这样您就可以将函数名称空间中绑定的实际函数作为值。
您还可以使用symbol-function
获取函数名称空间值,以便(symbol-function 'square)
计算与#'square
相同的函数。这具有可以作为setf
位置工作的功能,用于将函数名称空间中的某些内容设置为值。它仅在第二个参数实际上是函数时才有效:
(setf (symbol-function 'test) #'square)
(test square) ; ==> 100
defconstant
,defparameter
和defvar
未在函数名称空间中设置任何内容。 Thay只能用作普通变量,您也可以将其用于可以应用于funcall
和apply
的函数。
除了重新编译和重新编译之外,您应该避免将defconstant
用于除了允许系统内联的值之外的其他所有值,因为更改常量可能不会影响代码。在所有实际目的中,使用defparameter
和正确的+NAMING-CONVENTION+
将适用于明年可能会发生变化的+VAT+
等半常量!
Scheme没有常量,但R5RS中的零环境预计与原始程序使用的数据的工作方式相同,因此使用原始版本的常量折叠不会破坏任何内容。使用R6RS(可能还有R7RS),即使从其他import语句中也无法覆盖导入的表单。在Scheme中,您不能使用define
重新定义set!
,而是使用setf
和setq
来设置使用defparamater
或Common Lisp中的defvar
。