2

我正在寻找一种获取函数参数数量的方法,该函数类似于length-args下面的虚构函数:

(defun func1 (arg1 arg2) 
  ())

(defun get-count-args-func (func) 
  (length-args func))

(get-count-args-func #'func1)
;; return 2

在实践中,我真正需要的是从我的测试库中解决一个问题,我从 javascript 到 lisp,我在其中处理同步和异步测试,我需要做这样的事情(最大限度地简化现实) :

(defun test () 
  ;;...
  )

(defun done ()
  ;;...
  )

(defun run-test (test)
  (if (>= (get-count-args-func test) 1)
      (test (funcall done))
      (test)))
4

2 回答 2

1

我通过在此处查看此答案找到了解决此问题的方法:Find Function's Arity in common lisp,需要arglist函数来处理各种实现,请参阅arglist的实现:

;; function provided by @sds at https://stackoverflow.com/questions/15465138/find-functions-arity-in-common-lisp
(defun arglist (fn)
  "Return the signature of the function."
  #+allegro (excl:arglist fn)
  #+clisp (sys::arglist fn)
  #+(or cmu scl)
  (let ((f (coerce fn 'function)))
    (typecase f
      (STANDARD-GENERIC-FUNCTION (pcl:generic-function-lambda-list f))
      (EVAL:INTERPRETED-FUNCTION (eval:interpreted-function-arglist f))
      (FUNCTION (values (read-from-string (kernel:%function-arglist f))))))
  #+cormanlisp (ccl:function-lambda-list
                (typecase fn (symbol (fdefinition fn)) (t fn)))
  #+gcl (let ((fn (etypecase fn
                    (symbol fn)
                    (function (si:compiled-function-name fn)))))
          (get fn 'si:debug))
  #+lispworks (lw:function-lambda-list fn)
  #+lucid (lcl:arglist fn)
  #+sbcl (sb-introspect:function-lambda-list fn)
  #-(or allegro clisp cmu cormanlisp gcl lispworks lucid sbcl scl)
  (error 'not-implemented :proc (list 'arglist fn)))

现在我可以这样做:

(defun func1 (arg1 arg2) 
  ())

(defun get-count-args-func (func) 
  (length (arglist func)))

(get-count-args-func #'func1) => 2

所以我有参数的数量,你只需要注意,如果你有一些&key参数,&rest或者&optional,例如:

(defun func1 (&optional arg1 arg2) 
  ())

(defun get-count-args-func (func) 
  (length (arglist func)))

(get-count-args-func #'func1) => 3

看到你得到 3,因为arglist函数正在返回:

(&OPTIONAL ARG1 ARG2)

而他只返回了所需的参数:

(ARG1 ARG2)
于 2019-03-09T10:57:53.453 回答
0

最简单的方法是将剩余参数添加到您的函数中,并在函数中使用内置的长度函数来确定函数采用的 args 数量:

CL-USER> (defun fun-1(&rest args)
   (length args))
FUN-1
CL-USER> (fun-1 1 2 3)
3
于 2019-03-09T10:58:11.420 回答