Как проверить, объявлена ли переменная в perl?

Я использую use strict; в perl и с этим я использую следующий оператор.

unless(defined($x)){
      print "Not defined";
}

где $x нигде не объявлен. Поэтому я ожидаю, что он напечатает"Not defined", но он возвращает ошибку

Global symbol "$x" requires explicit package name at *********** in line 15.

7 ответов


The strict ПРАГМА имеет три части: строгие ссылки, строгие переменные и строгие подстановки. Вы работает в

строгий vars

это создает ошибку времени компиляции, если вы получаете доступ к переменной, которая не была объявлена через our или use vars, локализован через my, или не полное. Потому что это во избежание переменных проблем самоубийства и тонких динамических проблем с областью видимости, просто local переменная не хорошо достаточно.

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

{
  no strict 'vars';
  print "Not defined!\n" unless defined $x;
}

но обратите внимание, что Perl defined оператор сообщает вам, определено ли значение, а не объявлена ли переменная.

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


ты даже refer переменной, если она не объявлена. Когда вы спросите

defined( $x ) ?

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

если strict 'vars' не был включен--что по умолчанию, когда вы use strict--тогда он создаст запись в пакете таблица символов для 'X'.

интересно, что без strict 'refs' также легко проверить, находится ли переменная в таблице символов пакета.

defined( *{ __PACKAGE__ . '::x' }{SCALAR} )

поскольку нет способа автоматического создания лексических ("мои переменные"), также нет стандартного способа проверить, объявлены ли лексики. Лексические переменные хранятся в"pad". Но есть модуль PadWalker что может помочь.

для того чтобы проверить настоящий уровень, вы смогли получите хэш пэда, а затем проверьте, существует ли он в текущей пэде. Вы также можете выполнить цикл резервного копирования через стек (целочисленный аргумент работает примерно так:caller), чтобы найти, где последний x был.

my $h = peek_my (0);
exists $h->{x};

Я думаю, что вы смешиваете "определенные" и "объявленные" понятия.

Вы спрашиваете "Как проверить, объявлена ли переменная в perl", но затем вы проверяете, определена ли переменная. Это две разные концепции.

в Perl если вы используете 'use strict' вы автоматически проверяете любую переменную не заявлял (через мой, местные или наши). Как только у вас объявлена переменная, вы можно проверить, если он определен (имеет назначенное значение).

Так в тесте, вам не хватает предварительного декларирования до тестирования для defineness

use strict;
my $x;  # you are missing this part
[...] | # code
# your test for define
print defined $x? "defined\n" : "not defined\n";

имейте в виду, что тестирование только для $x неверно для вашей цели:

my ($x,$y, $z);
$w;         # not declared (use strict will catch it and die)
$x = 0;     # declared and defined BUT if you make a logic test like 'if ($x) {}' then it will be FALSE, so don't confuse testing for **'$x'** and testing for **'defined $x'**
$y = undef; # declared but not defined
$z = 1;     # declared, defined, and logial test TRUE

наконец, ответ ксенорратицида кажется мне ошибочным: он предлагает 'если $x' это не правильно для тестирования, если определено, как я сказал ранее. Он также предлагает 'если не существует $x', это неправильно для тестирование скаляров. тест "exists" предназначен только для ключей хэшей (и устарел для массивов).

надеюсь, что это помогает.


 #
 print "Not defined" if !defined($x);

результат будет

Не определен

 #
 use strict;
 print "Not defined" if !defined($x);

будет генерировать ошибку, как в вашем вопросе.

посмотрите на:http://perldoc.perl.org/strict.html, где описано, как вы можете импортировать только необходимые ограничения. (Однако использовать строгий 'vars' очень хорошая идея :))


обычно такой код не требуется для серьезной программы, но все же почему бы не просто для удовольствия: (при условии строгого использования)

print "Not defined\n" unless eval 'ref($x)';

#!/usr/bin/perl -l

use strict;

# if string below commented out, prints 'lol' , if the string enabled, prints 'eeeeeeeee'
#my $lol = 'eeeeeeeeeee' ;
# no errors or warnings at any case, despite of 'strict'

our $lol = eval {$lol} || 'lol' ;

print $lol;

мое решение #!/ usr / bin / perl-l

use strict;

# if string below commented out, prints 'lol' , if the string enabled, prints 'eeeeeeeee'
#my $lol = 'eeeeeeeeeee' ;
# no errors or warnings at any case, despite of 'strict'

our $lol = eval {$lol} || 'lol' ;

print $lol;