Какова польза блоков CHECK, UNITCHECK и INIT в Perl?
Я знаю, что они все делают, но никогда не оказывался в ситуации, когда я нуждался в любом из них. Во многих случаях я использовал блоки BEGIN
и END
. BEGIN
особенно полезен, когда вам нужно настроить среду до запуска кода, и я использовал END
в некоторых ситуациях отладки, чтобы улавливать важную информацию о состоянии для неуправляемых ошибок с жестким треком.
Вы когда-нибудь использовали CHECK
, UNITCHECK
или INIT
? Если да, зачем? А по какой-то причине блок BEGIN
не хватило бы?
Документация для блоков находится на PerlDoc.
Ответы
Ответ 1
У меня была функция пакета import
, которая выполняла бы большую обработку, а затем вызывала вызов eval
. Как вы отлаживаете что-то подобное? Функция импорта запускается, когда вы use
модуль, который имеет место во время компиляции (например, в блоке BEGIN). По какой-то причине (я думаю, это связано с тем, что мне нужно было передавать параметры import
с помощью записи heredoc, но это могло быть что-то еще), было недостаточно сказать require Module; Module->import(@args)
.
Итак, моим обходным путем было построение строки для eval
в import
и сохранение ее другой переменной.
Затем я запустил eval
в блоке INIT
. Когда вы запускали отладчик, первая точка выполнения была в начале блока INIT
, и я мог использовать отладчик для выполнения инструкции eval
.
Ответ 2
Интересное использование блоков CHECK содержится в "Расширенном программировании на Perl" Саймона Козенса (O'Reilly) в главе 1 в разделе "Делать вещи позже с CHECK". Он показывает, как реализовать "окончательный" java-атрибут
Кроме того, Devel:: Sub:: Trace использует блоки INIT для включения следов (эта информация относится к POD для Devel:: Hook, который является модулем, используемым для работы с этими именованными блоками)
Ответ 3
Колодки BEGIN
будут выполняться во время компиляции, как вы знаете. Поэтому я держу его в коде, который нужно запустить, чтобы мой модуль был импортирован.
Я написал обертку script, чтобы сделать все, что было сделано в шаблоне, который произошел в нескольких сотнях скриптов.
- Были вещи, которые я должен был сделать, чтобы получить чтение модуля
use
-d. Это я побежал в блоках BEGIN
и import
sub.
- Но был и тот шаблон, который инициализировал сервисы, которые будет использовать script. Поэтому я выполнил эти действия в блоках
INIT
.
- И выполнил необходимый код очистки и выхода в блоках
END
.
Я думаю, что CHECK имеет смысл, если вы пишете модули с двигателями XS, но я использовал их только несколько раз. Однажды я думаю, что нужно было проверить предложения в Intermediate Perl. И я не могу забыть другие причины.
Но я использую блоки INIT
, когда чувствую, что код является большей частью script, чем настройка модуля. По сути, я делаю только то, что необходимо во время компиляции.
Ответ 4
perlmod объясняет эти специальные блоки, но на самом деле используются только BEGIN
и END
.
Это всего лишь массивы CV, LIFO или FIFO.
Эти блоки позволяют выполнять отдельные тайминги при запуске кода независимо от местоположения в исходном файле. Таким образом, вы можете хранить разделы кода вместе, но они выполняются в разное время (PHASES
).
CHECK был добавлен сначала для запуска пакета компилятора O (-MO=C...
) в фиксированном порядке после инициализации модуля (использование пакета) и перед основной программой, чтобы сохранить там контекст выполнения. Это отделяет время компиляции (до) от времени выполнения (после).
perl -c
останавливается после ПРОВЕРКИ.
Поскольку я являюсь разработчиком компиляторов, я использую CHECK и -MO = широко. Мои модули compile()
методы вызывается O внутри блока CHECK. С Один (отладка O) я вызываю метод compile
не в CHECK, а позже в INIT, поэтому отладчик переходит в него. Отладчик не переходит в блоки CHECK по умолчанию, вы должны принудительно использовать его с помощью $DB::single=1
или использовать Od.
UNITCHECK был добавлен позже к компиляции и загрузке мелкозернистого модуля, особенно. .pmc
.
Я никогда не использовал это до сих пор. Это также может произойти во время выполнения, поэтому я могу использовать его для проверки типов загружаемых модулей времени выполнения.
INIT был добавлен, чтобы разрешить отдельную инициализацию класса.
Я редко использую это, но это удобно.