http://www.perlmonks.org?node_id=954288

rajan has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I am a beginner in Perl. My Question is,

#!/usr/local/bin/perl eval{ my $a=5; get_accounts(); }; sub get_accounts { print $a; }

When I execute the program, perl prints Nothing. Does declaring $a inside eval block will affect the scope ? As far as I studied, I believe that eval block will not hide any value, and also I understand that $a is a global variable. Please help me in understanding this concept. Regards, Rajan.

Replies are listed 'Best First'.
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.

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.

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.

      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.


      Improve your skills with Modern Perl: the free book.

      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;
      Instead of using strict and warnings, one should use common::sense.
        Common sense is to use strict and warnings.
        $ 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.

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
      You've noticed that when you do an eval, the print is "invisible"; however there is a way to get around that.

      What does Devel::Eval do in this case? There's no string eval in the original code; you changed the exception handling code to do something completely different! The real problem is one of lexical scoping.

        Thanks Every one .. I will use Strict in my programs.

Re: Doubt in Eval
by LanX (Saint) on Feb 16, 2012 at 17:30 UTC
    I think you meant:

    #!/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

    Cheers Rolf