Re: Scoping question
by Mutant (Priest) on Nov 03, 2004 at 20:44 UTC
|
Variables declared with 'my' only become visible after the current statement has finished (ie. ended with ';'). Thus, under strictures, you must declare the variable on at least the statement before you use it.
I would probably use:
my $item = $self->grid($x, $y);
push @{$self->{'select'}}, $item if $item;
| [reply] [d/l] |
|
|
push @{ $self->{select} }, $self->grid($x, $y) || ();
Update: I see Roy Johnson already posted essentially the same code at Re: Scoping question, though he opted to use or with parentheses instead of ||, as I used. | [reply] [d/l] [select] |
|
|
I do like this one a lot because, even though I have access to grid, it's called elsewhere where a scalar result is expected. The "|| ( )" makes for an elegant one-liner that eliminates the temporary variable completely. Thanks! And many thanks to all of you for the thoughtful discussion!
| [reply] |
|
|
Re: Scoping question
by Roy Johnson (Monsignor) on Nov 03, 2004 at 21:33 UTC
|
Just for fun (and any possible enlightenment this brings), you can do it with this one-line expression:
push @{$self->{'select'}}, (my $item = $self->grid($x, $y) or ());
While you can't use $item before the end of the statement, you can use the return value from the my (which is, not surprisingly, the same value). If the value is false, you push an empty list, which doesn't change the array.
And if you don't need $item elsewhere, you can just leave the assignment out:
push @{$self->{'select'}}, ($self->grid($x, $y) or ());
Caution: Contents may have been coded under pressure.
| [reply] [d/l] [select] |
Re: Scoping question
by duff (Parson) on Nov 03, 2004 at 20:58 UTC
|
my $item = $item;
The first $item on the line is the one you're declaring lexical while the second $item is whatever $item is available in the enclosing scope. Your lexical $item isn't available until after that statement has completely executed.
Perl 6 will change this behavior and make variables available as soon as possible. In order to get the old behavior you'll need to do something like:
my $item = $OUTER::item;
| [reply] [d/l] [select] |
|
|
use strict;
use warnings;
my $item = $item;
You will get:
Global symbol "$item" requires explicit package name at a.pl line 4.
Execution of a.pl aborted due to compilation errors.
Update:
see bpphillips's reply to my post, duff could actually meant what dpphillips detailed below. | [reply] [d/l] [select] |
|
|
I think your interpretation of duff's example is different than intended. Consider:
use strict;
use warnings;
my $item = "a";
if(1){
my $item = $item;
}
This compiles fine with no errors... | [reply] [d/l] |
|
|
Re: Scoping question
by BrowserUk (Patriarch) on Nov 03, 2004 at 21:08 UTC
|
If the grid method is under your control, then you can alleviate the need for the temporary var $item, and the conditional by arranging for it to return the empty list rather than undef when it has nothing to return.
#! perl -slw
use strict;
sub grid{
return $_[0] ? 12345 : ();
}
my @array = 1 .. 4;
print "@array";
push @array, grid( 1 );
print "@array";
push @array, grid( 0 );
print "@array";
__END__
[20:55:29.43] P:\test>junk
1 2 3 4
1 2 3 4 12345
1 2 3 4 12345
As you can see, pushing the empty list onto the array has no effect upon it, so you save the need to test the return and a temporary variable.
If it isn't under your control and you need to use the temp var and a test, your second working form is probably slightly preferable to the first as at least the temp var goes away, and should you need to do the same thing further down you can use the same temp var name and code form without conflict.
#! perl -slw
use strict;
sub grid{
return $_[0] ? 12345 : ();
}
my @array = 1 .. 4;
print "@array";
if( my $item = grid( 1 ) ) {
push @array, $item;
}
if( my $item = grid( 1 ) ) {
push @array, $item;
}
print "@array";
__END__
[21:01:53.53] P:\test>junk
1 2 3 4
1 2 3 4 12345 12345
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
"Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
| [reply] [d/l] [select] |
Re: Scoping question
by Wonko the sane (Curate) on Nov 03, 2004 at 20:38 UTC
|
Hello
The problem is, that the 'my $item' declaration only happens if the '$self->grid($x, $y)'
call actually returns something.
Other wise, there is no 'my' declaration, so you get the error stating that the
'$item' var is not known about.
Hope that helps
Wonko
Update: I stand corrected. Thank you pg | [reply] |
|
|
"The problem is, that the 'my $item' declaration only happens if the '$self->grid($x, $y)'
call actually returns something."
There is some gap in this explaination, as $self->grid($x, $y) is before that and operator, obviously it returns first. If what you said was true, then at the time you go evaluate what's after that and operator, $item is already there, and there should be no problem.
This really has nothing to do with the actual execution of the code, but rather the way, the interpreter parses the code.
| [reply] |
Re: Scoping question
by ikegami (Patriarch) on Nov 03, 2004 at 23:58 UTC
|
(What I said was completely wrong.) | [reply] |