Common Lisp如何调用关联列表中存储的引用lambda?
问题根因
调用失败的核心原因是定义关联列表*db*时使用了单引号'(即quote运算符):quote会完全阻止内部表达式求值,此时alist中存储的不是可执行的lambda函数对象,而是(lambda (a b) (+ a b))结构的普通S表达式列表,自然无法直接通过funcall调用。
修复方法
推荐方案:定义alist时正确存入函数对象
将外层单引号替换为反引号`,在每个lambda表达式前添加逗号,,让lambda在alist定义阶段就被求值为可调用的函数对象:
(defvar *db* `((:add ,(lambda (a b) (+ a b))) (:sub ,(lambda (a b) (- a b))))) (defun perform-operation-on-numbers (operation a b) "Performs specified operation on the supplied numbers." (let ((func (second (find operation *db* :key #'car)))) (funcall func a b))) ;; 测试调用,:add 1 2 将返回正确结果3 (perform-operation-on-numbers :add 1 2)
备选方案:调用时转换表达式为函数
如果不修改alist的原有定义,可以在取出列表结构的lambda表达式后,手动将其转换为函数对象再调用,该方案性能和安全性弱于前者,仅作兼容参考:
(defun perform-operation-on-numbers (operation a b) "Performs specified operation on the supplied numbers." (let ((func (second (find operation *db* :key #'car)))) (funcall (coerce func 'function) a b)))
注意:Common Lisp中lambda表达式只有被求值为函数对象后,才能被
funcall/apply调用;被quote包裹的lambda仅为普通列表,不具备可执行属性。
内容的提问来源于stack exchange,提问作者myTerminal
相关产品推荐
相关产品推荐

