17.4 函数式语法 (Functional Syntax)

另一个可以改善的空间是消息调用的语法。 tell 本身是无谓的杂乱不堪,这也使得动词在第三顺位才出现,同时代表着我们的程序不再可以像一般 Lisp 前序表达式那样阅读:

  1. (tell (tell obj 'find-owner) 'find-owner)

我们可以使用图 17.5 所定义的 defprop 宏,通过定义作为函数的属性名称来摆脱这种 tell 语法。若选择性参数 meth? 为真的话,会将此属性视为方法。不然会将属性视为槽,而由 rget 所取回的值会直接返回。一旦我们定义了属性作为槽或方法的名字,

  1. (defmacro defprop (name &optional meth?)
  2. `(progn
  3. (defun ,name (obj &rest args)
  4. ,(if meth?
  5. `(run-methods obj ',name args)
  6. `(rget ',name obj)))
  7. (defun (setf ,name) (val obj)
  8. (setf (gethash ',name obj) val))))
  9. (defun run-methods (obj name args)
  10. (let ((meth (rget name obj)))
  11. (if meth
  12. (apply meth obj args)
  13. (error "No ~A method for ~A." name obj))))

图 17.5: 函数式语法

  1. (defprop find-owner t)

我们就可以在函数调用里引用它,则我们的代码读起来将会再次回到 Lisp 本来那样:

  1. (find-owner (find-owner obj))

我们的前一个例子在某种程度上可读性变得更高了:

  1. > (progn
  2. (setf scoundrel (obj)
  3. patriot (obj)
  4. patriotic-scoundrel (obj scoundrel patriot))
  5. (defprop serves)
  6. (setf (serves scoundrel) 'self
  7. (serves patriot) 'country)
  8. (serves patriotic-scoundrel))
  9. SELF
  10. T