Как реализуются прагмы Perl с лексической областью видимости?

StackOverflow https://stackoverflow.com//questions/11711804

Вопрос

Прагмы, как autodie, согласно документации, имеют лексическую область видимости.

{
use autodie;
  ..
  ..
}
# Can die here

Это относится ко всем модулям, загруженным с use?Насколько я знаю, use почти то же самое, что:

BEGIN {
  require autodie;
  autodie->import(LIST);
}

BEGIN происходит во время компиляции, и require не имеет лексической области видимости.Так как autodie осознаете его масштаб?

Это было полезно?

Решение

Короткий ответ: лексическая область видимости прагматические модули явно написаны для такого поведения и используют магические внутренние переменные $^H и %^H во время компиляции для включения и отключения функций.

Компилятор играет свою роль, неявно локализуя эти переменные, чтобы их значение восстанавливалось в конце компиляции блока кода до того, которое было в начале.Таким образом, он обеспечивает основу лексической семантики.

Первоначально только $^H переменная была доступна.Он содержит битовую маску, которая определяет, какие параметры компилятора доступны в любой момент компиляции.По этой причине единственными лексическими прагмами, которые можно было написать, были те, которые манипулировали определенным набором магических битов в $^H.

Позже %^H был введен хеш, и теперь любая прагма может хранить значения в этом хэше с ключами, начинающимися с имени прагмы.Поскольку компилятор локализует хэш так же, как и скаляр, любая прагма может хранить здесь информацию о статусе с автоматически ограниченной областью действия.

А autodie модуль не манипулирует ни одной из этих переменных, а создает подклассы Fatal модуль, который делает всю тяжелую работу.Оно использует %^H чтобы отслеживать, какие операторы стали фатальными, и полагается на то, что компилятор отбрасывает эту информацию в конце блока.

Другие советы

Из метода импорта Fatal.pm который является серверной частью autodie, наслаждайся:

# Dark magic to have autodie work under 5.8
# Copied from namespace::clean, that copied it from
# autobox, that found it on an ancient scroll written
# in blood.

# This magic bit causes %^H to be lexically scoped.
$^H |= 0x020000;

Итак, ответ заключается в том, что действительно существует способ сделать ваш импорт осведомленным об их лексической области, но он глубоко связан с внутренностями Perl и не предназначен для использования обычными программистами.

Это не require Это интересно;это то, что делает прагма import.

Большинство (все?) прагм используют $^H или %^H.Анализатор локализует их в анализируемой области, то есть восстанавливает их значение, которое они имели раньше.

Брать строгий, например.Его import изменяет $^H. $^H содержит ряд флагов, которые указывают компилятору, как себя вести.

$ perl -e'
    BEGIN { printf "%04X\n", $^H }
    {
       use strict;
       BEGIN { printf "%04X\n", $^H }
    }
    BEGIN { printf "%04X\n", $^H }
'
0100
0702
0100

$^H зарезервировано для использования в Perl, но аналогично локализовано %^H доступен для общего пользования.Например, функция::qw_comment подключается к парсеру один раз, когда он загружается require, но ничего не делает, если только $^H{'feature::qw_comments::'} правда.Его импорт эквивалентен

sub import { $^H{'feature::qw_comments::'} = 1; }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top