В LISP можно получить доступ к форме функции?
-
27-10-2019 - |
Вопрос
Предположим, я определяю функцию во всем мире:
(defun x (y) (1+ y)) ;; Edit: my first example was too complicated
Можно ли «принуждать» функцию x в список, подобный:
(x (y) (1+ y))
Заранее спасибо!
PS-Пример Danlei работает в Clozure CL с специальным флагом, однако кто-нибудь знает, как заставить функциональную экспрессию-экспрессию для работы в SBCL?
Решение
Вы могли бы попробовать Функция-ламбда-экспрессия:
(function-lambda-expression #'foo)
Но это не гарантированно сработает («… реализации могут вернуть« ноль, правда, ноль »во всех случаях…»).
Например, в 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
, так что вы, вероятно, испытаете худшую производительность.
Другие советы
В общем виде, вы мощь иметь возможность восстановить определение функции, используя function-lambda-expression
(См Hyperspec) или в некоторых реализациях uncompile-function
.
Когда я проводил время на проекте, чтобы выполнить значительные функции манипуляции, было проще всего делать такие вещи:
(defclass node ()
(list-form
compiled-obj))
Сначала была бы назначена форма списка, состоящая из «(Lambda Foo (x) Bar), а затем я бы скомпилировал Foo и назначил его в слот скомпилированным ojb.