You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取Common Lisp函数的参数数量?附测试库适配场景

实现函数参数统计与同步/异步测试调度

看起来你是要把JavaScript测试库的逻辑搬到Common Lisp里,核心需要先搞定「获取函数参数个数」的能力,再用它区分同步和异步测试——思路很清晰,咱一步步来实现。

第一步:实现获取函数参数数量的工具函数

Common Lisp本身没有直接的length-args函数,但我们可以用function-lambda-list来获取函数的lambda列表,再统计参数数量。先写最基础的版本:

(defun get-count-args-func (func)
  (length (function-lambda-list func)))

测试你给的示例:

(defun func1 (arg1 arg2) ())
(get-count-args-func #'func1) ; 直接返回2,完美符合预期

如果你的测试函数可能包含可选参数、关键字参数这类特殊情况,可以优化成只统计必填的位置参数——毕竟异步测试一般都是明确需要一个done回调作为必填参数的:

(defun get-required-arg-count (func)
  (let ((lambda-list (function-lambda-list func)))
    (length (loop for elem in lambda-list
                  until (member elem '(&optional &rest &key &aux &allow-other-keys))
                  collect elem))))

这个版本会忽略&optional及之后的所有特殊标记和参数,只统计前面的必填位置参数,更贴合测试场景的需求。

第二步:实现同步/异步测试的调度逻辑

有了参数统计函数,就能实现你要的run-test逻辑了。先放完整的代码示例,包括测试函数和回调:

;; 示例同步测试函数:不需要done回调
(defun test-sync ()
  (format t "执行同步测试...~%"))

;; 示例异步测试函数:需要接收done回调
(defun test-async (done)
  (format t "执行异步测试...~%")
  (funcall done) ; 异步操作完成后调用done标记结束
)

;; 测试完成的回调函数
(defun done ()
  (format t "测试已完成!~%"))

;; 核心测试调度函数
(defun run-test (test)
  (if (>= (get-required-arg-count test) 1)
      (funcall test #'done) ; 异步测试:传入done回调
      (funcall test))) ; 同步测试:直接执行

逻辑说明:

  • 当测试函数的必填参数个数≥1时,判定为异步测试,调用时传入done回调,让测试在完成后主动触发结束信号
  • 当测试函数没有必填参数时,判定为同步测试,直接执行即可

小提示

如果你的测试函数是用lambda定义的闭包,function-lambda-list同样能正常工作,比如:

(defun test-closure (done)
  (let ((internal-val 42))
    (format t "闭包测试:~a~%" internal-val)
    (funcall done)))

(get-required-arg-count #'test-closure) ; 返回1,没问题

内容的提问来源于stack exchange,提问作者PerduGames

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 06:24:31