Re: Doubt in Eval
by LonelyPilgrim (Beadle) on Feb 16, 2012 at 17:28 UTC
|
I'm not far above an initiate myself. But yes, declaring $a with my within the eval limits its scope only to that eval block -- as declaring anything with my makes it a lexical variable limited to whatever { } block it is within (not just eval; the same goes for a sub or 'for' or any block). If you want a global variable -- why do you want a global variable? If you just want something that's visible to both your eval and your sub, you could declare 'my $a' outside both blocks -- (creating a lexical variable at the package level). It would do what you need it to do, and make it effectively 'global' to your script here.
Does this sound confusing? Sorry. I am still figuring out scope myself. I read this excellent article on scope the other day (discovered in a link here). It is kind of old, but timeless (in recent versions of Perl, 'our' declarations are recommended over 'use vars' for package variables).
In any case, I would recommend the pragmata "use warnings 'all'" and "use strict" to help you catch issues like this. It's particular helpful when you're learning, but recommendable always.
| [reply] |
|
| [reply] |
Re: Doubt in Eval
by jethro (Monsignor) on Feb 16, 2012 at 17:43 UTC
|
if you declare $a with 'my' it is not a global variable. Use 'our' for that. Also the eval is a block that will hide lexical variables declared inside.
| [reply] |
Re: Doubt in Eval
by Anonymous Monk on Feb 16, 2012 at 17:28 UTC
|
$a is exempt from strict checking, so let's use a different variable name. Let's enable the pragmas strict and warnings to point out mistakes that beginners are liable to make. I'll demonstrate that the eval statement is a red herring, it can be removed and the same problem still shows: "Global symbol "$aa" requires explicit package name at…"
#!/usr/bin/env perl
use strict;
use warnings;
sub get_accounts {
print $aa;
}
my $aa = 5;
get_accounts();
Lesson to learn: pass parameters to functions, do not rely on lexical variables leaking into the function from an outer scope. (Globals are okay.) To help enforce this through coding style, always place subroutine definitions before the main part of the code. | [reply] [d/l] |
|
I'll demonstrate that the eval statement is a red herring....
It's not a red herring: you changed the order of the code and thus its behavior. When the parser encounters $aa in your example, it hasn't seen the declaration three lines later.
If you had merely removed the eval block, the result would run just fine without the variable declaration error.
| [reply] [d/l] |
|
As a footnote, the reason that $a is exempt from strict checking, is because it is one of the magic variables that you can use to specify a custom comparison to sort
For example, suppose you have a list of hashes, and you want to sort by the value of a key, you might write:,
my @persons_by_age = sort { $a->{'age'} <=> $b->{'age'} } @people;
| [reply] [d/l] [select] |
|
Instead of using strict and warnings, one should use common::sense.
| [reply] |
|
Common sense is to use strict and warnings.
| [reply] |
|
|
|
|
$ corelist strict warnings Common::Sense
strict was first released with perl 5
warnings was first released with perl v5.6.0
Common::Sense was not in CORE (or so I think)
$
Requiring the installation of a module that does little but save typing? Virtuous Laziness is not about pushing work off onto others.
Additionally strict refs is more useful than not & can be easily disabled in the few scopes that it actually gets in the way.
I agree w/ zwon. Common Sense is better w/o the double colon. | [reply] [d/l] |
Re: Doubt in Eval
by Khen1950fx (Canon) on Feb 16, 2012 at 18:02 UTC
|
$a and $b are special variables in Perl, so you want to use some other letter for your variable. You've noticed
that when you do an eval, the print is "invisible"; however there is a way to get around that. Use
Devel::Eval.
#!/usr/bin/perl -l
use strict;
use warnings;
use Devel::Eval qw( dval );
my $x = '';
dval <<'EOF';
if ($x= 5) {
get_accounts();
}
sub get_accounts {
print $x;
}
EOF
| [reply] [d/l] [select] |
|
| [reply] |
|
| [reply] |
Re: Doubt in Eval
by LanX (Saint) on Feb 16, 2012 at 17:30 UTC
|
#!/usr/local/bin/perl
my $a;
eval{
$a=5;
get_accounts(); # prints 5
};
sub get_accounts {
print $a;
}
Did you really want a block-eval? There are differences between eval EXPR and eval BLOCK, see eval
| [reply] [d/l] |