schema 和 emacs lisp(实际上是大多数其他 lisp)之间的一个重要区别是,scheme 有一个命名空间,而 emacs lisp 有单独的函数和变量命名空间。计算的列表形式中的第一个位置命名了一个函数,并且在函数名称空间中查找该名称。在方案中,所有名称都位于同一空间中,无论它出现在何处,都会查找并使用与该名称绑定的值。
这意味着在 emacs lisp 中你可以这样:
(defun f (x) (+ x x))
(setq f 2)
(f f) ;=> 4
这在方案中是不可能的,这里只有一个f
如果你设置它的值,它就会从(比如说)一个函数变成一个数字。
在 emacs lisp 中有不同的方法来处理这个问题。
一种是使用诸如funcall
and apply
,它们接受一个函数和一些参数,并将函数应用于参数,如下所示:
(setq f (lambda (x) (+ x x)))
(funcall f 2) ;=> 4
另一种方法是操纵函数名称f
方法。有一个函数叫做fset
允许您将函数附加到名称(在函数命名空间中):
(fset 'f (lambda (x) (+ x x x)))
(f 2) ;=> 6
注意fset
适用于名称(又名符号),因此名称f
需要加引号,否则会被读取为变量的值。这就是为什么调用变量函数的原因setq
,“q”代表“引用”,所以setq
实际上是一个特殊的函数,它引用它的第一个参数,这样程序员就不必这样做。有一个等效的普通函数称为set
不做任何引用,如:
(setq x 1) ; x is 1
(set 'x 2) ; x is 2
(setq x 'x) ; x is the symbol x
(set x 3) ; x is now 3
最后一种形式可能看起来令人困惑,但作为set
是一个范式,它会查找变量的值x
,该值是符号x
然后命名将要更改的变量(即x
)。因此,优点之一是set
的优点是可以设置您不知道名称但可以通勤的变量。