ПрограммированиеPerl разработчик / Ведущий разработчик по поддержке Perl-проектов

Объясните, как работает лексический и динамический scoping в Perl, когда используется my, local и our, и приведите примеры проблем при неверном понимании этих различий.

Проходите собеседования с ИИ помощником Hintsage

Ответ

В Perl переменные могут иметь лексическую или динамическую область видимости.

  • my создаёт переменную с лексическим scoping: переменная видима только внутри блока, где определена.
  • local временно переопределяет значение глобальной (package) переменной с динамическим scoping: новое значение видно во всех вызванных функциях до выхода из блока.
  • our определяет глобальную (package) переменную, но видимую только в текущем лексическом блоке.

Пример:

our $x = 10; sub test_my { my $x = 20; inner(); } sub test_loc { local $x = 30; inner(); } sub inner { print $x; } test_my(); # Выведет 10 — my $x не виден из inner $| = 1; test_loc(); # Выведет 30 — local $x виден из inner

local используется для изменения package-переменных типа специальных $_, $/, $@ и др.

Вопрос с подвохом

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

our $a = 5; sub outer { my $a = 10; inner(); } sub inner { print $a; } outer();

Ответ: Выведет 5. Потому что my-переменная $a из outer невидима из inner; используется package-переменная $a, объявленная через our.

Примеры реальных ошибок из-за незнания тонкостей темы


История

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

История

В модульном тестировании многие разработчики переопределяли глобальные спец. переменные типа $/ (разделитель строк) через my, в результате изменений не происходило, тесты «падали» странным образом только частично.

История

В JavaScript-разработке после перехода на Perl разработчики по привычке старались объявлять переменные с помощью our везде без необходимости, что приводило к появлению неожиданно глобальных переменных, мешающих инкапсуляции и появлению пересечений имён.