Найти Arity функции в общем lisp

Я занимался генетическим программированием и разделял функции на разные наборы функций в зависимости от их арности; это все довольно сложно.

Я хотел бы знать, есть ли более простой способ сделать это. Например, если есть функция, которая возвращает арность заданной функции.

Приветствия заранее.

1 ответ

Решение

Для интерпретируемых функций вы должны быть в состоянии использовать function-lambda-expression,

Для скомпилированных функций, увы, эта функция часто возвращаетnil, так что вам придется использовать функцию, зависящую от реализации ( clocc/ port/ sys.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)))

РЕДАКТИРОВАТЬ: обратите внимание, что arity в CL на самом деле не число, так как функции Lisp могут принимать необязательные аргументы, аргументы rest и ключевое слово в дополнение к необходимым; вот почему выше arglist Функция возвращает лямбда-список аргументов функции, а не число.

Если вас интересуют только функции, которые принимают только обязательные параметры, вам нужно использовать что-то вроде

(defun arity (fn)
  (let ((arglist (arglist fn)))
    (if (intersect arglist lambda-list-keywords)
        (error "~S lambda list ~S contains keywords" fn arglist)
        (length arglist))))

Существует портативная библиотека, которая предоставляет лямбда-список функции: https://github.com/Shinmera/trivial-arguments

(ql:quickload "trivial-arguments")

Пример:

(arg:arglist #'gethash)
;; => (sb-impl::key hash-table &optional sb-impl::default)

(defun foo (a b c &optional d) nil)
(arglist #'foo)  ;; => (a b c &optional d)

Возвращает полный лямбда-список, с &optional и так далее, поэтому мы не можем просто получить length результата для arity.

Другие вопросы по тегам