← Архив: Common Lisp

декларирование зависимостей между пакетами

Author: · 04.10.2017 14:31
· original author: den73
Иногда при рефакторинге пакеты переставляются местами по порядку сборки. Тогда может получиться так, что из пакета :клиент вызывается символ сервер:символ, а пакета :сервер ещё нет. В интерактивном режиме это сработает, а при пересборке образа возникнет ошибка чтения из несуществующего пакета. Чтобы обострить эту проблему и сделать зависимости между пакетами декларативной, можно в определении пакета :клиент писать 
(:import-from :сервер) - тогда нельзя будет создать :клиент раньше, чем :сервер
В принципе, такие зависимости должны описываться в asdf-системах, но бывает несколько пакетов на asdf-систему, тогда asdf не поможет. 
У меня также есть функция budden-tools:*fn-before-return-symbol-from-reader-hook*, к-рая позволяет перехватить момент, когда reader возвращает символ, и проверить, что если *package* == :клиент, а прочитано сервер:символ, то (assert (пакет-клиент-использует-или-импортирует-пакет-сервер)). На данный момент - только SBCL, в прошлом был и Lispworks. С помощью такого перехвата можно сделать так, что и при интерактивной разработке будет ругаться. 
Правда, нельзя делать такую проверку тотальной, ведь иногда граф зависимостей пакетов не является деревом - из :сервер тоже может быть прочитан символ клиент:имя. Т.е. нужно ещё расширить defpackage, чтобы ему можно было указать, является ли ссылка на пакет обязательной для того, чтобы прочитать символ из этого пакета с квалификатором. 
https://bitbucket.org/budden/budden-tools/src/46d10362973a75672921281e33d2d34af8136eff/careful-token-reader.lisp?at=default&fileviewer=file-view-default
Реализация такой идеи слегка улучшает модульность в лиспе. Пока что я начал в новых пакетах писать (import-from пакет), но переделывать остальное руки не дойдут ли когда-нибудь. 
За участие в разработке идеи спасибо linkfly. 
· original author: den73
P.S. кстати, если код в пакете :клиент читает сервер:символ, а код в пакете :сервер читает клиент:символ, то нужно бы добавить декларацию (forward-referenced :клиент) в определение пакета сервер. Тогда читатель лиспа поймёт, что ссылка есть, но с поздним связыванием - пакет клиент не обязан существовать в момент определения пакета сервер. А если не :use, не :import-from и не :forward-referenced, то тогда уже ругаться. Это не даёт 100% проверки связей между пакетами во время чтения, но представляет хорошее приближение к нему. 
· original author: shamaz.mazum
Я тебе проще скажу. Собираешь первым файло packages.lisp, где находятся defpackage'ы.
> У меня также есть функция budden-tools:*fn-before-return-symbol-from-reader-hook*,
А я сегодня сходил в туалет по большому.