Как заменить работающую функцию в Common Lisp? - PullRequest
6 голосов
/ 16 января 2012

Предположим, мы используем SBCL # 'save-lisp-and-die для создания серверного приложения App1, которое работает очень хорошо.Теперь мы хотим заменить функцию # 'func1 новой версией, не останавливая App1.Как мы можем сделать это в Common Lisp?

Любые предложения приветствуются!

Ответы [ 2 ]

10 голосов
/ 16 января 2012

Я лично гарантирую, что SWANK (серверная часть SLIME) работает, так что я могу в любой момент подключиться к образу с помощью Emacs + SLIME и переопределить все, что захочу.

(ql:quickload "swank")
(swank:start-server :port 1234) ;; listen for SLIME connections on port 1234

Затем вEmacs, вы можете M-x slime-connect и следовать подсказкам.

Если вы не хотите делать это по какой-либо причине, ваша реализация может предложить что-то конкретное.

4 голосов
/ 17 января 2012

Вам необходимо загрузить новое определение функции. Тогда новая функция будет доступна немедленно; код вызовет вновь загруженную функцию.

Новое определение функции может быть загружено разными способами:

  • (load (compile-file "file.lisp")), где file.lisp - исходный код функции
  • (load "file.fasl") где file.fasl - скомпилированный исходный код
  • (eval (defun ...))

Конечно, есть исключения и осложнения:

  • Это не заменит уже запущенные вызовы предыдущих функций; например, бесконечный цикл событий не может быть изменен таким образом - он должен поддерживать некоторую остановку и вызов новой функции. Однако такие длительные функции встречаются редко. Это можно обойти, используя рекурсию вместо цикла (но не все компиляторы выполняют оптимизацию хвостовых вызовов).
  • Если вы где-то захватили указатель на функцию (например, (function FOO), где FOO - имя функции), она сохранит свое старое значение. Чтобы избежать этого, используйте символы вместо указателей на функции (символы funcall способны).
  • Код функции подлежит сборке мусора. Вы должны быть осторожны, чтобы не оставлять ссылки на старые версии функций. Кроме того, если некоторые функции становятся ненужными, вы не должны забывать fmakunbound их символы.
  • Если функция использовалась во время компиляции, весь уязвимый код также должен быть перезагружен
  • Если бы у вас были высокие уровни оптимизации (что не по умолчанию), компилятор мог бы встроить функцию в другие. CLHS различает случаи, когда переопределение функции становится «неопределенным поведением».

Но на практике перезагрузка кода хорошо работает в большинстве реализаций Common Lisp.

...