В LISP возможно ли получить доступ к форме функции?
Предположим, я определил функцию глобально:
(defun x (y) (1+ y)) ;; Edit: my first example was too complicated
Можно ли "привести" функцию x в список, например:
(x (y) (1+ y))
Заранее спасибо!
PS - пример @Danlei работает в Clozure CL со специальным флагом, однако кто-нибудь знает, как заставить FUNCTION-LAMBDA-EXPRESSION работать в SBCL?
3 ответа
Вы можете попробовать FUNCTION-LAMBDA-EXPRESSION:
(function-lambda-expression #'foo)
Но работа не гарантируется ("… реализации могут возвращать" nil, true, nil "во всех случаях…").
Например, в CCL:
CL-USER> (setq ccl:*save-definitions* t)
T
CL-USER> (defun x (x y) (+ x y))
X
CL-USER> (function-lambda-expression #'x)
(LAMBDA (X Y) (DECLARE (CCL::GLOBAL-FUNCTION-NAME X)) (BLOCK X (+ X Y)))
NIL
X
В SBCL вы можете попробовать (setq sb-ext:*evaluator-mode* :interpret)
(Непроверенные). Возможно, есть и другие способы добиться этого в SBCL (вы можете найти аналог *save-definitions*
или даже попробовать разные OPTIMIZE
настройки), но я не знаю о них. Помните, что функции, введенные в REPL, не будут скомпилированы после установки *evaluator-mode*
в :interpret
так что вы, вероятно, будете испытывать худшую производительность.
В Common Lisp вы можете восстановить определение функции, используя function-lambda-expression
(см. HyperSpec) или в некоторых реализациях uncompile-function
,
Когда я тратил время на проект для выполнения значительных манипуляций с функциями, было проще всего делать такие вещи:
(defclass node ()
(list-form
compiled-obj))
Сначала должна быть назначена форма списка, состоящая из '(lambda foo (x) bar), затем я скомпилирую Foo и назначу ее в слот compiled-ojb.