lisp 表达式求值规则
一个要求值的 lisp 对象被称为lisp表达式(form)。
lisp 表达式分三种
1. 自求值表达式。前面说过数字、字符串、向量都是自求值表达式。还有两个特殊的符号 t 和 nil 也可以看成是自求值表达式。
2. 符号表达式。符号的求值结果就是符号的值。如果它没有值,就会出现 void-variable 的错误。
3. 列表表达式。关键看第一个元素
列表的第一个表达式如果是一个符号,解释器会查找这个符号的函数值。如果函数值是另一个符号,则会继续查找这个符号的函数值。
这称为“symbol function indirection”。符号功能追踪
最后直到某个符号的函数值是:
1. lisp 函数(lambda 表达式)、byte-code 函数、原子函数( primitive function).
这是正常的函数调用(function call),求值规则如下:
先对列表中其它元素求值,求值的结果作为函数调用的真正参数。
然后使用 apply 函数用这些参数调用函数。
可以理解为把参数和变量绑定到函数后,对函数体顺序求值,返回最后一个 form 的值。
2. 宏、
将宏展开。如果扩展后还是一个宏调用,则会继续扩展下去,直到扩展的结果不再是一个宏调用为止。
3. 特殊表达式或 autoload 对象。
这些特殊表达式通常是用于控制结构或者变量绑定。例如IF语句,WHEN 语句等
每个特殊表达式都有对应的求值规则
4. 以上类型都不是,
比如某个符号的函数值是前面出现的某个符号导致无限循环,
或者某个符号函数值为空,
都会导致一个错误 eval: Symbol’s function definition is void: ...
最后用这个elisp 伪代码来说明一下 elisp 中的求值规则:
(defun eval (exp)
(cond
((numberp exp) exp)
((stringp exp) exp)
((arrayp exp) exp)
((symbolp exp) (symbol-value exp))
((special-form-p (car exp))
(eval-special-form exp))
((fboundp (car exp))
(apply (car exp) (cdr exp)))
(t
(error "eval: Symbol's function definition is void: %S" exp))))
参考1: elisp 手册
参考2: 网上资料