Если вы увидели это предупреждение в Perl-скрипте, у вас большие неприятности.

Присваивание значения переменной

Присваивание значения переменной, но не использование ее, или использование переменной единожды, вообще не присвоив ей значения, вряд ли будет корректным в любом коде.

Возможно, единственное разумное объяснение - вы допустили опечатку, что и привело к появлению переменной, используемой лишь однажды.

Вот пример кода, в котором мы только присваиваем значение переменной:

use warnings;

$x = 42;

Выполнение его приведет к предупреждению:

Name "main::x" used only once: possible typo at ...

Эта часть с "main::" и отсутствие $ могут вас смутить. "main::" здесь потому, что по умолчанию любая переменная в Perl относится к основному пространству имен main. Существует также пара вещей, которые могут называться "main::x", и только у одной из них есть в начале $. Если это звучит немного запутанно, не беспокойтесь. Это и есть запутанно, но можно надеяться, что вам не придется иметь дела с этим в течение долгого времени.

Только получение значения

Если получилось так, что вы используете переменную лишь однажды

use warnings;

print $x;

то вы, скорее всего, получите два предупреждения:

Name "main::x" used only once: possible typo at ...
Use of uninitialized value $x in print at ...

Об одном из них сейчас и идет речь, а о другом вы можете прочесть в статье Use of uninitialized value.

О какой опечатке речь?

Могли бы вы спросить.

Представьте, что кто-то использует переменную под названием $l1. Потом приходите вы и хотите использовать ту же переменную, но пишете $ll. В зависимости от используемого шрифта, они могут выглядеть очень похоже друг на друга.

Или, возможно, существует переменная $color, но вам ближе британский язык, так что вы автоматически написали $colour, имея в виду эту переменную.

Или у вас была переменная $number_of_misstakes, и вы не заметили ошибки в исходном названии, и написали $number_of_mistakes.

В общем, понятно.

Если вам повезет, вы ошибетесь только однажды, а если не повезет, и вы напишете название неправильно дважды, то это предупреждение не появится. В конце концов, если вы используете одну переменную дважды, на это, должно быть, есть причина.

Так как же избежать этого?

Для начала, постарайтесь избегать названий переменных с неоднозначным написанием, и будьте внимательны, набирая их.

Если же вы хотите действительно решить эту проблему, просто используйте use strict!

use strict

Как видно в предыдущих примерах, мы не использовали strict-режим. Если бы мы его включили, то вместо предупреждения о возможной опечатке мы бы получили ошибку компиляции: Global symbol requires explicit package name.

Это происходило бы даже если вы использовали неверную переменную больше одного раза.

Конечно, кто-то мог бы просто, не подумав, поставить "my" перед неправильной переменной, но вы-то не из таких, не так ли? Вы бы подумали над проблемой и нашли бы, как действительно должна называться переменная.

Наиболее типичный способ увидеть это предупреждение - не использовать strict.

И вот тогда-то у вас возникнут серьезные неприятности.

Другие случаи при использовании strict

Как указали GlitchMr и анонимный комментатор, существуют и некоторые другие случаи:

Этот код также может выдать такое:

use strict;
use warnings;

$main::x = 23;

Вы увидите предупреждение: Name "main::x" used only once: possible typo ...

Здесь по крайней мере понятно, откуда взялось 'main', или в следующем примере, откуда взялось 'Mister'. (подсказка. Это название модуля, которого не хватало другой ошибке про названия модулей.) В следующем примере название модуля - 'Mister'.

use strict;
use warnings;

$Mister::x = 23;

Мы увидим предупреждение Name "Mister::x" used only once: possible typo ....

Следущий пример тоже выдает это предупреждение. Дважды:

use strict;
use warnings;

use List::Util qw/reduce/;
print reduce { $a * $b } 1..6;

Name "main::a" used only once: possible typo at ...
Name "main::b" used only once: possible typo at ...

Это происходит потому, что $a и $b - специальные переменные, используемые во встроенной функции сортировки (

sort

), поэтому их не нужно объявлять; однако здесь они используются только один раз. (На самом деле мне непонятно, почему здесь эти предупреждения появляются, хотя в таком же коде с использованием sort - нет, но Perl Monks могут знать.)