Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if variable is declared in perl?

Tags:

perl

I am using use strict; in perl and with that I use the following statement.

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

Where $x is not declared anywhere. So I expect it to print "Not defined" but it returns an error

Global symbol "$x" requires explicit package name at *********** in line 15.
like image 411
Shubham Avatar asked Aug 21 '10 11:08

Shubham


4 Answers

The strict pragma has three parts: strict references, strict variables, and strict subs. The one you're running into is

strict vars

This generates a compile-time error if you access a variable that wasn't declared via our or use vars, localized via my, or wasn't fully qualified. Because this is to avoid variable suicide problems and subtle dynamic scoping issues, a merely local variable isn't good enough.

Because it generates compile-time errors, your non-BEGIN code won't even have a chance to run. You can temporarily allow non-strict variables inside a block as in

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

but note that Perl's defined operator tells you whether a value is defined, not whether a variable has been declared.

Tell us more about your application, and we can give you better advice about how to handle it.

like image 138
Greg Bacon Avatar answered Oct 09 '22 21:10

Greg Bacon


You can't even refer to a variable unless it's declared. When you ask

defined( $x ) ?

the compiler is going to complain: I don't know this what you're asking about, how am I supposed to tell it is defined? It has no point of reference for that variable, since you've indicated you do not want variables auto-created by name.

If strict 'vars' was not on--which it is by default when you use strict--then it would create an entry in the package symbol table for 'x'.

Interestingly enough is that without strict 'refs' it is also easy to check if a variable is in the package symbol table.

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

Since there is no way to auto-create a lexical ("my variables"), there is also not a standard way to check to see if lexicals are declared. Lexical variables are stored in the "pad". But there is a module PadWalker that can help.

In order to check the current level, you could get a hash of the pad, and then check whether or not it exists in the current pad. You could also loop back up through the stack (the integer argument works something like caller) to find where the most recent x was.

my $h = peek_my (0);
exists $h->{x};
like image 30
Axeman Avatar answered Oct 09 '22 19:10

Axeman


I think you are mixing 'defined' and 'declared' concepts.

Your are asking for 'How to check if variable is declared in perl' but then you are checking if a variable is defined. These are two different concepts.

In perl if you use 'use strict' you are automatically checking for any variable not declared (using my, local or our). Once you have a variable declared, you can test if it is defined (have a value assigned).

So in your test, you are missing a prior declaration before testing for defineness

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

Please be aware the testing for only $x is incorrect for your purpose:

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

Finally the answer of xenorraticide seems faulty to me: he suggest 'unless $x' that is not correct for testing if defined as I said before. He also suggest 'unless exists $x', that is wrong for testing scalars. 'exists' test is only for hashes keys (and deprecated for arrays).

Hope this helps.

like image 30
Pablo Marin-Garcia Avatar answered Oct 09 '22 19:10

Pablo Marin-Garcia


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

result will be

Not defined

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

will generate error as in your question.

Look to: http://perldoc.perl.org/strict.html, where described how you can import only required restrictions. (However use strict 'vars' is very good idea :) )

like image 44
Michael Pakhantsov Avatar answered Oct 09 '22 20:10

Michael Pakhantsov