scoping question
nmerriweather
created: 2006-03-02 11:34:11
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.
Re: scoping question
created: 2006-03-02 11:38:32
Declaring variables once at the beginning of the code block where they are being first used is the best practice imo. One other alternative 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.
_____________________
"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
Re^2: scoping question
created: 2006-03-02 11:47:40
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() )
{
    # use $_ inside this block...
    $obj->do_this();
}
elsif     ( $_ = $obj->create_id() )
{
    # use $_ inside this block
    $obj->do_that();
}
else
{
    $obj->do_somethingelse();
}
Re: scoping question
created: 2006-03-02 11:39:28

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 weird, so I would probably take the my $id; outside of the if.

Re: scoping question
created: 2006-03-02 17:29:54
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
created: 2006-03-02 22:14:04
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.

perlmonks.org content © perlmonks.org and Anonymous Monk, ikegami, nmerriweather, vladb

prlmnks.org © 2006 edmund von der burg (eccles & toad)

v 0.03