Продолжаю мучаться с системой модулей. Уже почти в депрессию впал - настолько это оказалось трудно.
Как будет устроен файл в Л2
Кусок кода делится на интерфейс и реализацию. Интерфейс и реализация находятся в разных файлах (как в С). Сборка происходит путём построения графа «зависимых действий».
Структура файла примерно такая:
// -*- для_чтения : "зависимое_действие1 ... зависимое_действиеN"; -*-
пространство_имён ИМЯ;
зависит_от зависимое_действие1 ... зависимое_действиеN ;
... собственно код ...
В общем-то это похоже на C с его инклюдами.
Зависимые действия
Зависимое действие - это файл (цель) и указание, что с ним нужно сделать. Что можно сделать?
1. Прочитать - это означает, что файл будет распарсен и записан куда-то в память.
2. Загрузить - это означает, что он будет откомпилирован и динамически слинкован. В ходе этого процесса будут (пере)определены описанные в файле функции и типы и выполнены команды инициализации.
Зависимости в С и в Лиспе
И вот тут у меня вопрос. В С просто указывается имя файла, а дальше система сама ищет его по путям.
В лиспе же есть «системы», хотя их надо бы назвать «модулями».
Система в лиспе является набором файлов и в то же время единицей зависимостей для сборки образа. Внутри системы - свои зависимости между файлами.
Лисп ищет систему (по путям или другим способом). Внутри системы имена файлов заданы жёстко.
Иллюзия циклических ссылок
Сравнивая работу в Лиспе и в Дельфи, я увидел, что в Дельфи работать намного удобнее. Мне казалось, что дело в циклах, и я даже многих обругал. Но я ошибался. В Дельфи нет циклических ссылок.
unit b; interface uses a;
end. {EOF}
unit a; interface ; implementation uses b;
end. {EOF}
Казалось бы, это циклическая зависимость. На самом же деле Дельфи компилирует интерфейс и реализацию отдельно и необязательно сразу, а зависимость возможна только от интерфейса. Поэтому это _не_ циклическая зависимость.
В Лиспе тоже надо отделить интерфейс от реализации системы
В лиспе же обычно ОДНА и та же система содержит пакет (интерфейс) и код (реализацию). Из-за этого и проблемы с порядком сборке в лиспе, которых нет в Дельфи. Нужно бы в лиспе завести традицию выделять пакет (и другой интерфейс) в одну систему, а реализацию - в другую систему.
Тогда на лиспе стало бы легче управлять системами. Не считая, конечно, того, что в Дельфи нужно писать меньше слов.
А что делать в Л2
Как же сделать, чтобы было хорошо, в новом языке? Уже понятно, что нужно отделить интерфейс от реализации, но это только часть решения. Как управляться с файлами?
Вижу два варианта:
1. Сделать как в С - единицей сборки и зависимости является отдельный файл, который ищется по помойке путей. Тут очевидно вылезает проблема уникальности имён. Я на С больших проектов не писал, может я чего-то не знаю о том, как решается эта проблема?
2. Сделать как в лиспе, т.е. ввести два уровня иерархии - систему и файл. Система содержит свой файл .asd. Но! Важное отличие от лиспа состоит в том, что система не является единицей сборки, а служит лишь для поиска файлов. Например, если мы нашли где лежит mysystem.asd, то файл mysystem.myfile.л2 находится там же. А, скажем, mysystem/dir1/f2.л2 - находится в подкаталоге dir1.
Зависимости же задаются в виде
действие(система.файл_внутри_системы)
а действие может быть «прочитать» или «загрузить». Если в системе принято стандартом хранить интерфейс в файле интерфейс.л2, то построить зависимость от интерфейса легко, зная только имя системы.
При этом где-то должно храниться знание о том, где лежит данная система. Но в asdf эта задача уже решена (даже слишком уж навороченно решена).
Собственно и вопрос - надо ли морочиться с «системами» или достаточно файлов? И может быть, кто-нибудь может это соотнести с другими языками (не знаю, как это сделано в Java и C#).