Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris

scoping question

by nmerriweather (Friar)
on Mar 02, 2006 at 16:34 UTC ( #533962=perlquestion: print w/replies, xml ) Need Help??
nmerriweather has asked for the wisdom of the Perl Monks concerning the following question:

The following code creates this scoping error:
"my" variable $id masks earlier declaration in same scope
if ( my $id = $obj->get_id() ) { $obj->do_this(); } elsif ( my $id = $obj->create_id() ) { $obj->do_that(); } else { $obj->do_somethingelse(); }
a quick fix was to replace it with this:
my $id ; if ( $id = $obj->get_id() ) { $obj->do_this(); } elsif ( $id = $obj->create_id() ) { $obj->do_that(); } else { $obj->do_somethingelse(); }
however, i'm wonderng if there's another way.

Replies are listed 'Best First'.
Re: scoping question
by ikegami (Pope) on Mar 02, 2006 at 16:39 UTC

    You're getting the error because all the if and elsif expressions execute in the same scope (which starts with the if and ends with the last 'then', elsif or else clause). You just need to remove the second my since the first one is still in effect.

    if ( my $id = $obj->get_id() ) { $obj->do_this(); } elsif ( $id = $obj->create_id() ) { $obj->do_that(); } else { $obj->do_somethingelse(); }

    However, I find the lack of symetry in the above code weird. I would probably do as you did and place a my $id; outside of the if. You can add curlies around the my and the if if you wish to tighten the scope.

Re: scoping question
by vladb (Vicar) on Mar 02, 2006 at 16:38 UTC
    Declaring variables once at the beginning of the code block where they are being first used is the best practice imo. One other alternative (yet poor) approach is to use the special $_ variable.
    if ( $_ = $obj->get_id() ) { # use $_ inside this block... $obj->do_this(); } elsif ( $_ = $obj->create_id() ) { # use $_ inside this block $obj->do_that(); } else { $obj->do_somethingelse(); }
    Generally, however, this wouldn't be a very sound approach, as it is usually very easy to loose track of the $_ variable. Although, it does spare you having to declare variables, especially for short code blocks or loops.

    Update: As ikegami pointed out (++), I stress that the use of $_ is a bad idea. I just wanted to show one alternative, albeit a bad one as a means of warning against such approach. :)
    "We've all heard that a million monkeys banging on a million typewriters will eventually reproduce
    the entire works of Shakespeare. Now, thanks to the Internet, we know this is not true." - Robert Wilensky, University of California
      Don't assign to $_ without localizing it first! $_ is usually aliased to another variable, and your code would clobber it. The fix is to add local to the first assignment (as shown below). However, if you do that, you've gained nothing but obfuscation. You should use my $id instead of local $_.
      if ( local $_ = $obj->get_id() ) # XXX Use "my $id =" instead of { # "local $_ =" for clarity. $obj->do_this(); } elsif ( $_ = $obj->create_id() ) # XXX Use "$id =" instead of { # "$_ =" for clarity. $obj->do_that(); } else { $obj->do_somethingelse(); }
Re: scoping question
by Anonymous Monk on Mar 02, 2006 at 22:29 UTC
    I agree with ikegami that the lack of symetry feels weird, even though its perfectly valid code.

    Personally, I'd take the second approach but specificially limit the scope of $id (by use if the outer {}s).
    { ### Do this or that for $obj my $id; if ( $id = $obj->get_id() ) { $obj->do_this(); } elsif ( $id = $obj->create_id() ) { $obj->do_that(); } else { $obj->do_somethingelse(); }; }; { ### Do this and that for $next_obj my $id; if ( $id = $next_obj->get_id() ) { $next_obj->do_this(); } elsif ( $id = $next_obj->create_id() ) { $next_obj->do_that(); } else { $next_obj->do_somethingelse(); }; };
Re: scoping question
by nmerriweather (Friar) on Mar 03, 2006 at 03:14 UTC
    Yeah, it was the lack of symmetry that had me put 2 my's in there. i understand why things are scoped like that, but I don't like it view-wise. looking at it, i would expect the my to be valid within the if, and not the else. i know its not, but i'm trying to balance symmetry / clear to look at , with tight scoping.

    thanks all for the advice.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://533962]
Approved by Old_Gray_Bear
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (6)
As of 2018-11-13 06:30 GMT
Find Nodes?
    Voting Booth?
    My code is most likely broken because:

    Results (150 votes). Check out past polls.