如何向Lambda表达式函数传递变量?用宏实现包内函数Lambda列表获取
获取包内所有函数的Lambda列表方案及问题解决
SBCL环境下的实现
在SBCL中,借助iterate工具可以直接获取包内所有函数的Lambda列表,代码如下:
(use-package :iterate) (defun lambda-lists (package) (iter (for symbol in-package (find-package package)) (collect (sb-introspect:function-type symbol))))
可移植性尝试的问题
为了提升代码的可移植性,你可能会尝试使用标准函数function-lambda-expression来实现,但直接这样写会报错:
(defun lambda-lists (package) (iter (for symbol in-package (find-package package)) (collect (function-lambda-expression symbol))))
核心问题是:function-lambda-expression要求参数是函数对象,而非符号。直接使用(function symbol)也不可行,这会试图创建名为symbol的函数,而非获取符号当前绑定的函数对象。
用宏实现需求的方案
可以通过宏解决这个问题,宏能在编译期处理符号,将其转换为对应的函数对象。示例代码如下:
(defmacro lambda-lists-macro (package) `(iter (for symbol in-package (find-package ,package)) (when (fboundp symbol) (collect (function-lambda-expression (symbol-function symbol))))))
这里做了两个关键处理:
- 用
symbol-function从符号中取出对应的函数对象,传递给function-lambda-expression - 增加
(fboundp symbol)判断,过滤掉包内非函数类型的符号
调用宏时直接传入包名即可:
(lambda-lists-macro :common-lisp)
向Lambda表达式传递变量的方法
function-lambda-expression返回的是Lambda表达式的定义形式,而非可直接调用的函数对象。如果要调用它,需要先对返回的Lambda表达式求值,再传入参数:
(let* ((lambda-expr (function-lambda-expression #'+)) (lambda-func (eval lambda-expr))) (funcall lambda-func 1 2)) ; 输出3
如果已经持有函数对象,直接用funcall调用即可,无需先获取Lambda表达式:
(funcall (symbol-function '+) 1 2) ; 输出3
内容的提问来源于stack exchange,提问作者user3414663
相关产品推荐
相关产品推荐

