|
уже не могу вспомнить, почему я не разрешил нормальное определение типов внутри процедуры. то есть, наследника записи можно, а методы ему — нельзя. чёрт его знает что такое. разрешил и методы: это очень удобно для всяких `Walk`, которым передаётся контекст с абстрактным методом `Do`. если что — проблемы доступа к апвалуям (то бишь, переменным внешней процедуры) отсутствуют, потому что такой доступ отсутствует у всех. оно несложно, но вот не хочу. когда надо — делается явная запись-контекст и явно же передаётся.
также в следующей версии будут вложеные модули. и в этой бы сделал, но уже лень ковыряться, пусть хоть какой-то стимул пилить следующую будет.
вложеный модуль — это, по сути, просто отдельное пространство имён, но с гиммиком: вложеный модуль имеет полный доступ ко всему из внешнего (то бишь, к непублиным переменным, процедурам, etc.), а внешний из внутреннего может дёргать только то, что public. на диске, естественно, внутреннего модуля как отдельной сущности не существует.
rationale: у меня есть привычка разбивать код на совсем маленькие независимые части. иногда для этого можно использовать процедуру, в которую прячутся все потроха, но иногда процедуры мало. а городить некий абстрактый интерфейс, который нужен только вот здесь внутри, но бесстыдно торчит наружу просто от отсутствия способа сделать его ограничено видимым… не нравится. что наружу высунуто — то, сталбыть, для всех, обязательно будет использовано. к тому же обычно добавляются лишние тормоза за счёт виртуальных вызовов. и даже если их нет, то компилятор вынужден инлайнить через границы модулей. фи.
ну, например, хэш-табличка: обычно реализация настолько одинаковая, что её можно скопипастить (как я часто и делаю). но мусорить в модуль внутренними именами из неё — зачем? делать её отдельным модулем — значит, высовывать наружу интерфейс, нужный только для реализации этой хэш-таблички (по сути, интимные детали, которые в любой момент могут поменяться — типа методов `Hash()` и `Equals()`), или заворачивать каждый элемент в отдельную запись с `ANYPTR`, передавать внешнюю реализацию `Hash()` и `Equals()`… короче, сплошная морока без какой-либо реальной необходимости — тупо сражение с компилятором.
с внутренним модулем же ничего лишнего наружу высовывать не надо, и во внешний модуль ничем не мусорим (кроме — увы — неизбежных интрузивных деклараций тех же `Hash()` и `Equals()`). как по мне — стало чище и лучше. реализация несложная (можно обойтись простым name mangling, тупо складывая всё с изуродоваными именами в самый верхний модуль — тогда в компиляторе меняется почти ничего).
возможно, кто-то скажет, что это хак для тех, кому лень придумывать нормальные интерфейсы… и я соглашусь. иногда никакого смысла тратить усилия на то, что нужно сугубо локально, нет. но некоторую защиту кишков копипасты (что обеспечивает чуть более безопасную возможность заменить потом эту копипасту другой) иметь всё-таки полезно.
в схеме и форте я вложеными модулями активно пользуюсь — не вижу, почему в обероне надо этого лишаться.
|