"my @x if condition" is quite dangerous, because it creates a kind of global variable with restricted scope! If this is in a subroutine, the second time you call the sub, you get exactly the same array, not a new one.
But anyway.. this switch-like initiation is very common, and I like to write it like this:
my @xxx = $op eq 'numbers' ? (one, two, three)
: $op eq 'alpha' ? (four, five)
: $op eq 'alp' ? (six, ten)
: die; # or ()
Just one of many ways to express the same. | [reply] [d/l] |
use strict;
use warnings;
sub mytest {
my $var if 0;
$var++;
print $var, "\n";
}
mytest();
mytest();
__OUTPUT__
1
1
We see several important things in that snippet. First, there are NO errors under strictures, and no warnings. Second, $var is NOT the same variable each time mytest() is called. If we had created a closure, the output would have been 1 and 2, not 1 and 1. If we had autovivified a global, we would have gotten a strictures error, or at minimum, the output would have been 1 and 2. But none of that happens. We get a new lexical variable each time mysub() is called.
Why?
Because my has two elements to how it works. First, the compiletime side. At compiletime, the framework is made for a lexical variable. Yet at compiletime, it is too soon to know the outcome of program logic. So the lexical is created without any regard for logic; all that matters is lexical scope.
At runtime, logic springs to life. And if the "my" declaration has an assignment component to it, as in my $x = 10 if $condition; that assignment will only take place if $condition is true. But $x exists within the lexical block whether or not $condition is ever true. And it falls out of scope just like any good lexical would, when the lexical block ends, even if its a subroutine.
| [reply] [d/l] [select] |
I don't know if it's considered the right way to do, but it'll take away the errors ;)
my @xxx = ();
@xxx = ("one", "two", "three") if ( $op eq "numbers" );
@xxx = ("four", "five") if ( $op eq "alpha" );
@xxx = ("six", "ten") if ( $op eq "alp" );
| [reply] [d/l] |
samy1212,
Perhaps your problem is with scoping. If that's the case, you should take a look at the Tutorials section, in particular:
- Coping with Scoping off site
- Variable Scoping in Perl: the basics
When you declare a variable - you are not only declaring it's name (what follows the leading sigil), it's type (scalar, hash, array, typeglob, etc), you are also declaring it's scope. When you declare a variable with my, you are restricting its scope to the nearest enclosing curly braces.
Probably what you want to do is change its current value and not actually declare it again:
my @array = qw(1 2 3);
@array = qw(one two three) if $op eq 'alpha';
Conditionally declaring a variable is generally considered a bad idea and can lead to problems down the road. So your code would change to:
my @xxx;
@xxx = qw(one two three) if $op eq 'numbers';
@xxx = qw(four five) if $op eq 'alpha';
@xxx = qw(six ten) if $op eq 'alp';
Finally, if you want to use the same variable name, but in different scopes - that is perfectly acceptable:
#!/usr/bin/perl -w
use strict;
hello('world');
goodbye('world');
sub hello {
my $greeting = shift;
print "hello $greeting\n";
}
sub goodbye {
my $greeting = shift;
print "goodbye $greeting\n";
}
I hope this helps - L~R | [reply] [d/l] [select] |
Just move the variable declaration above the first if modifier e.g
my @xxx;
@xxx = (one, two, three) if ( $op eq "numbers" );
@xxx = (four, five) if ( $op eq "alpha" );
@xxx = (six, ten) if ( $op eq "alp" );
You'll no longer get the warning as you won't be declaring the @xxx multiple times (as lexicals are declared at compile-time (i.e when it's putting the program together)).
| [reply] [d/l] |
You need to distinguish between the concepts of "declaring" a lexical variable (using "my" to let the compiler know about it)
and initializing or setting it. While you can do both in one statement, there is no need to (and if the assignment is conditional there may be need not to).Just declare the variable first (my @xxx;) and then set it in a separate statement (just the way you have it is fine, once the my's are removed and a my @xxx; added at the top).
The warning you got should alert you that each time you say
my @xxx, you are creating a new variable named @xxx and hiding the old one: almost certainly not what you want.
Others have warned you of the evils of my whatever if condition; perldoc perlsyn says:
NOTE: The behaviour of a my statement modified with a statement
modifier conditional or loop construct (e.g. my $x if ...) is
undefined. The value of the my variable may be undef, any
previously assigned value, or possibly anything else. Don't rely on
it. Future versions of perl might do something different from the
version of perl you try it out on. Here be dragons.
| [reply] [d/l] [select] |
thanks to all for the help
| [reply] |
Just declare my @xxx once.
my $op = "numbers"; # for example
my @xxx = qw(one two three) if ( $op eq "numbers" );
@xxx = qw(four five) if ( $op eq "alpha" );
@xxx = qw(six ten) if ( $op eq "alp" );
print "@xxx\n";
results in:
one two three
A.A. | [reply] [d/l] [select] |