Добавить название пакета в символ - PullRequest
0 голосов
/ 31 августа 2018

Это общий символьный вопрос в определенном контексте. Вопрос, на который мне нужно ответить: заданный параметр, содержащий символ «foo», как мне манипулировать частью пакета символа, чтобы он соответствовал «package: foo?»

Более конкретный контекст: существует пакет для модульного тестирования fiveam, в котором функции теста хранятся в хэш-таблице (it.bese.fiveam::*tests) с ключами типа package::test-name, которые хэшируют объект, содержащий тесты. Для запуска теста обычно передают функции run! символ, который является хеш-ключом: (run! 'package::test-name. Если я звоню run! из пакета tests, в котором я определил тесты, я могу просто C-x C-e на (run! 'test-name). При звонке из SLIME REPL я должен сделать (tests::run! 'tests::test-name), что вызывает легкие неудобства.

Я бы хотел запустить тесты от cl-user с (run! 'test-name) и опустить имя пакета. Я думал, что было бы просто обернуть run! и добавить недостающий пакет к символу, но все мои попытки провалились, я думаю, отчасти потому, что CL-USER:test-name отличается от tests:test-name.

В рассматриваемой хеш-таблице eql используется для проверки равенства. В пакете tests:

(eql 'tests::foo 'foo) => T

В CL-USER:

(eql 'tests::foo 'foo) => nil

Различные функции могут возвращать символы (например, intern, make-symbol или format-symbol), но ни одна из них не соответствует ключам в хэш-таблице:

(eql (alexandria:format-symbol t "foo::bar") 'foo::bar) => nil
(eql (make-symbol "foo::bar") 'foo::bar) => nil

Извлекая это из контекста SLIME / REPL / FIVEAM, чтобы обобщить, где, на мой взгляд, проблема, я не могу понять, как взять 'bar и превратить его в 'foo:bar в качестве символа. Я могу указать это вручную как 'foo:bar, но я не могу получить что-нибудь для eql 'foo:bar, учитывая 'bar.

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

Спасибо.

Ответы [ 2 ]

0 голосов
/ 01 сентября 2018

Вы можете использовать функцию import для импорта нужных символов:

(import '(fiveam:run! my-tests::foo))

Импортирует оба символа в ваш текущий пакет (вы также можете указать другой пакет в качестве другого аргумента). Вы можете тогда

(run! 'foo)

Если вы попытаетесь выполнить этот импорт после некоторых неудачных попыток, вы можете оказаться в отладчике, где вы можете выбрать соответствующий перезапуск, чтобы разрешить конфликт между символами с одинаковым именем (что-то вроде «ВЗЯТЬ НОВУЮ»).

0 голосов
/ 31 августа 2018

Прежде всего, я предполагаю, что вы знаете, что вы можете переключиться на пакет test в SLIME REPL, используя расширенную команду in-package (т. Е. В приглашении REPL введите запятую ,, а затем in-package, вам будет предложено ввести имя пакета), и переключение таких пакетов просто неудобно для вас.

Одним из решений может быть введение небольшой вспомогательной функции в любой пакет, в котором вы сейчас работаете:

(defun run-test (name &optional (package 'test))
   (funcall (find-symbol #.(symbol-name 'run!) package)
            (find-symbol (symbol-name name) package)))

или проще (и при условии, что определение run! пришло из пакета Fiveam через :use или :import в пакет test)

(defun run-test (name &optional (package 'test))
   (it.bese.fiveam:run! (find-symbol (symbol-name name) package)))

, который теперь можно назвать

(run-test 'check-everything)

Обратите внимание, что мы используем find-symbol здесь вместо intern, так как мы ожидаем, что символы существуют во всех случаях. Если вы хотите, чтобы помощник был легко доступен везде, вы можете даже сделать

(defun :run (name &optional (package 'test))
   (it.bese.fiveam:run! (find-symbol (symbol-name name) package)))

и теперь вы можете назвать его как

(:run 'check-everything)

в зависимости от текущего пакета. Обратите внимание, что я бы рекомендовал это только для помощников, предназначенных для использования в REPL. Подобное засорение глобального пространства имен (например, пространства имен функции ключевого слова) кажется мне немного странным.

На всякий случай: ни один из приведенных кодов не был протестирован (или даже пропущен через REPL), так что будьте осторожны. Кроме того, я искренне рекомендую прочитать главу о пакетах и ​​символах в CLHS, которую следует рассматривать как Ultimate Source ™ для этих вещей.

...