Разработка образа lisp

Мне нравится идея языков с изображением, и в последнее время я играл с Common Lisp через sbcl. В нескольких местах я читал о том, как можно сохранять и загружать изображение виртуальной машины, вы можете разработать приложение или набор приложений, работающих на этом изображении.

Я получаю, как загружать код в изображение и запускать его, слизь делает эту вещь очень приятной, но мой вопрос таков: как я могу определить, какие функции определены в изображении? Скажем, я хочу сделать обновление функции дней или месяцев после ее запуска, и я не могу вспомнить имя. Есть ли способ получить код или даже имена функций, определенных в изображении?

Теперь я записываю код в исходный код и загружаю его через repl, поэтому у меня есть копия, но похоже, что это будет очевидной особенностью.

Ответ 1

Общие Lisp имеют идею пакетов. Пакеты представляют собой реестр для символов и используются как пространства имен для символов. Вы можете запросить Common Lisp для списка всех пакетов.

CL-USER 1 > (list-all-packages)
(#<The SQL-COMMON package, 0/4 internal, 28/32 external>
 #<The LOOP package, 245/256 internal, 3/4 external>
 #<The COMM package, 0/4 internal, 940/1024 external>
 #<The REG package, 41/64 internal, 0/4 external>
 ...)

Каждый пакет хранит интернированные символы в некоторой структуре данных. Вы можете запросить Common Lisp, какие символы интернированы в пакете.

CL-USER 2 > (loop for symbol being
                each external-symbol in (find-package "COMMON-LISP")
             collect symbol)
(MAKE-ARRAY INVOKE-DEBUGGER STRING-TRIM ...)

Чтобы сделать это проще, Common Lisp предоставляет функции APROPOS и APROPOS-LIST.

CL-USER 3 > (apropos "MAKE-LOCK")
MP::INTERNAL-MAKE-LOCK (defined)
MP:MAKE-LOCK (defined)
WWW-UTILS:MAKE-LOCK (defined)
MAKE-LOCK
RESOURCES::MAKE-LOCK (defined)
MINIPROC:MAKE-LOCK (defined)

Функции, классы и т.д. используют символы в качестве их идентификатора. Вы также можете задать символ, обозначающий его функцию.

CL-USER 4 > (symbol-function 'www-utils:make-lock)
#<Function WWW-UTILS:MAKE-LOCK 41E006A69C>

Иногда Common Lisp также записывает определение функций. Затем функцию FUNCTION-LAMBDA-EXPRESSION можно использовать для извлечения "it".

CL-USER 5 > (defun foo (a) (* (sin a) a))
FOO

CL-USER 6 > (pprint (function-lambda-expression 'foo))

(LAMBDA (A)
  (DECLARE (SYSTEM::SOURCE-LEVEL #<EQ Hash Table{0} 41403151C3>))
  (DECLARE (LAMBDA-NAME FOO))
  (* (SIN A) A))

Но обычно в настоящее время Common Lisp реализация не использует записанные определения, а записывает местоположения источника для каждой конструкции Lisp.

Наиболее распространенные реализации Lisp могут отслеживать местоположения источников определенным образом.

Общий Lisp стандарт определяет функцию ED.

CL-USER 7 > (ed 'www-utils:make-lock)

Это вызывает редактор (внутренний или внешний) и должен открыть исходный код для этой функции. Чтобы выполнить эту работу, Common Lisp должен отслеживать местоположение источника для каждой функции. Затем редактор должен иметь доступ к этому источнику. Иногда записанное местоположение является абсолютным путем /Users/joswig/ lisp/utils.lisp. Если редактор хочет открыть этот файл, он должен быть доступен. Но также можно использовать логические пути, такие как http: server; utils.lisp. Затем он преобразуется в реальный физический путь. Позднее этот перевод можно настроить. Таким образом, можно было бы переместить Lisp на другую машину с разными путями, настроить логический путь HTTP, а затем Lisp все еще находит весь исходный код, даже если он находится на другой машине с другой структурой файловой системы, Поэтому для его работы может потребоваться некоторая конфигурация. Но это очень полезная функция, и она широко используется.

Как записывается исходный код и как работает запись местоположений источников, зависит от реализации и является функцией соответствующего Lisp в сочетании с его средой разработки. Более эффективные реализации Lisp имеют множество функций в этой области.

Ответ 2

Вы также можете использовать символы do или внешние символы, если хотите:

Пример:

>> (do-external-symbols (s (find-package :foo-package)) (print s))

FOO-PACKAGE:XXX
FOO-PACKAGE:YYY
FOO-PACKAGE:ZZZ
NIL

Где XXX, YYY и ZZZ - все внешние символы в пакете: foo-package.