Ответ 1
pragma Pure
Вы должны использовать это на любом пакете, который не имеет внутреннего состояния. Он сообщает, что пользователь пакета, который вызывает любые подпрограммы, не может иметь побочных эффектов, потому что нет внутреннего состояния, которое они могли бы изменить. Таким образом, функция, объявленная на уровне библиотеки внутри чистого пакета, всегда будет возвращать тот же результат при вызове с теми же параметрами.
Реализации Ada разрешено кэшировать возвращаемые значения функций чистого пакета и опускать вызовы подпрограмм, если их возвращаемые значения не будут использоваться из-за этих требований. Однако вы можете нарушить ограничения, вызвав импортированные подпрограммы (например, из библиотеки C) внутри вашего чистого пакета (это может изменить некоторое внутреннее состояние, которое компилятор Ada не знает). Если вы злы, вы можете даже импортировать подпрограммы Ada из других частей программного обеспечения с помощью pragma Import
, чтобы обойти требования pragma Pure
. Излишне говорить: если вы делаете что-то вроде этого, не используйте pragma Pure
.
Изменить: Чтобы прояснить обстоятельства, когда вызовы могут быть опущены, позвольте мне привести ARM:
Если модуль библиотеки объявлен чистым, тогда реализации разрешено пропустить вызов подпрограммы библиотечного уровня библиотечного модуля, если результаты не нужны после вызова. Точно так же он может опустить такой вызов и просто повторно использовать результаты, полученные более ранним вызовом в той же подпрограмме, при условии, что ни один из параметров не имеет ограниченного типа, а также адреса и значения всех фактических параметров для ссылки, а также значения всех фактических параметров by-copy-in, такие же, как и при предыдущем вызове. Это разрешение применяется, даже если подпрограмма вызывает другие побочные эффекты при вызове.
GNAT, например, дополнительно определяет, что любые подпрограммы, которые принимают параметр типа System.Address
или тип, полученный из него, не считаются чистыми, даже если они определены в чистом пакете, поскольку местоположение, на которое указывает адрес, может быть изменен, но GNAT не знает, на какую структуру указывает адрес, и поэтому не может выполнять никаких проверок о том, было ли изменено ссылочное значение параметра.
pragma Preelaborate
Это сообщает компилятору, что пакет не будет выполнять какой-либо код во время разработки (т.е. до начала выполнения основной процедуры). Во время разработки будут выполнены следующие конструкции:
- Инициализация переменных уровня библиотеки (это может быть вызов функции)
- Инициализация задач, объявленных на уровне библиотеки (они могут запускаться до выполнения основной процедуры)
- Заявления в блоке
begin ... end
на уровне библиотеки
Обычно вам следует избегать этих вещей, если они вам не нужны. Используйте pragma Preelaborate
, где это возможно, он сообщает вызывающему, что он может безопасно использовать пакет без каких-либо действий во время разработки.
Если что-то не скомпилируется с одной из этих прагм, когда вы думаете, что это нужно, посмотрите, почему он не компилируется. Это может помочь вам обнаружить проблемы с реализацией или структурой пакета. Не просто бросайте прагму, когда она не компилируется. Поскольку ограничение влияет на возможные ограничения на любые пакеты, зависящие от ваших, вы всегда должны выбрать самую строгую применимую прагму.