之前的fboundp函数能够告诉我们一个给定的符号是不是已经是一个函数的名字。如果一个符号是一个函数的名字,symbol-function会返回这个函数:
[1]> (fboundp '+)
T
[2]> (symbol-function '+)
#<SYSTEM-FUNCTION +>
通过设置某些名字的symbol-function到一个函数,
[5]> (setf (symbol-function 'add2) #'(lambda (x) (+ x 2)))
#<FUNCTION :LAMBDA (X) (+ X 2)>
我们就由此定义了一个全局函数,就像我们使用defun定义它一样:
[6]> (add2 1)
3
事实上,defun仅仅是将如下的形式
(defun add2 (x) (+ x 2))
翻译成上面的setf表达式。使用defun让程序看起来更亲切,并且可能会对比啊你一起提供一些帮助,但是严格说来,你不需要为做到这一点而写程序。
通过将defun的第一个参数设成(setf f)的形式,你就定义了setf的第一个参数是对f°的调用。下面的一对函数将primo定义成car的同义词:
(defun primo (lst) (car lst))
(defun (setf primo) (val lst)
(setf (car lst) val))
在名称为(setf f)这样形式的函数的定义中,第一个参数代表这个新值,后面的参数代表f°的参数。
现在任何primo的setf将变成上面后一个函数的调用:
[12]> (let ((x (list 'a 'b 'c)))
(setf (primo x) 480)
x)
(480 B C)
通常来说没有必要为了定义(setf primo)来定义primo,但是这样的定义通常是成对出现的。
因为字符串也是Lisp表达式,所以它们也可以出现在代码体中。一个字符串自身没有副作用,并且除非它是最后一个表达式,否则它不会有任何不同。如果你将字符串作为defun函数体的第一个表达式,
(defun foo (x)
"Implements an enhanced paradigm of diversity"
x)
那么这个字符串将变成函数的文档字符串。通过调用documentation函数可以将一个全局定义的函数的文档取出来:
[14]> (documentation 'foo 'function)
"Implements an enhanced paradigm of diversity"