Common lisp 如何获取函数的参数量

Common lisp 如何获取函数的参数量,common-lisp,arity,parameter-list,Common Lisp,Arity,Parameter List,我正在寻找一种方法来获取函数的参数量,一种类似下面虚构的length args函数的函数: (defun func1 (arg1 arg2) ()) (defun get-count-args-func (func) (length-args func)) (get-count-args-func #'func1) ;; return 2 实际上,我真正需要的是从我的测试库中解决一个问题,这个问题是我从javascript带到lisp的,我在这里处理同步和异步测试,我需要这样做

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

(defun func1 (arg1 arg2) 
  ())

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

(get-count-args-func #'func1)
;; return 2
实际上,我真正需要的是从我的测试库中解决一个问题,这个问题是我从javascript带到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)

最简单的方法是将rest参数添加到函数中,并在函数中使用内置的length函数来确定函数使用的参数数:

CL-USER> (defun fun-1(&rest args)
   (length args))
FUN-1
CL-USER> (fun-1 1 2 3)
3

对于我必须处理的情况,这不是一个选项,因为有时我传递一个“完成”参数,有时不,因为我同时处理同步和异步函数,异步需要一个“完成”参数,而同步不需要。我的搜索不是传递了多少个参数,而是函数请求了多少个参数,
get count args func
将是一个元函数,因为它处理函数元信息。我更新了我的问题,请看。@Rainer不,她在那里没有答案,她有办法。人们的搜索方式有所不同,使用另一个问题的关键词,他们可能没有找到提供路径的问题,最终会错过答案。所以我不认为这是一个重复的问题,而是一个基于另一个答案的不同问题,这是不同的事情,如果我没有把它连接到这里,你可能找不到另一个问题。你在问函数的算术,这就是另一个问题的内容,你把其中一个答案中的代码复制到了你自己的答案中。@Rainer“arity”这个词并没有出现在我的脑海中,对于很多人来说,它也不会出现。是的,所以我提供了一个链接,显示谁写了代码,它不是副本,它是引用,它是不同的东西,不要混淆术语;但你想怎么做就怎么做,你才是王者。@RainerJoswig我从编程中了解到,将事物解耦很有趣,你试图通过将这个问题标记为“重复”来实现事物的耦合,看看为什么:另一个问题是“在common lisp中查找函数的算术”,任何搜索它的人都会发现,虽然我的问题是“如何获得一个函数的参数数量”,但两个问题的答案都是一样的,对吧,完全相同的问题用不同的措辞发布并不罕见。然后可以将其标记为重复。你的问题不会消失:它会一直存在,人们可以找到它。但是,同一个问题在不同的地方有多个相同答案的版本几乎没有什么用处。这个便携库正是这样做的:
CL-USER> (defun fun-1(&rest args)
   (length args))
FUN-1
CL-USER> (fun-1 1 2 3)
3