Domanda

I have a loop that checks to see whether all the files in a directory are uploaded to the directory by checking to see if the number of files is constant.

Starting out, it knows that there are $before files in the directory ("before" it looks again).

use strict;
use warnings;
my $after = 0;
my $before ="10";

until($before == $after) {
    #check again, which changes the value of $after.
    #Now....
    $after = "20"; 

    if ( $after == $before ) {
        print "After is before. Moving out of until because all files are there!\n";
    }
    else {
        print "After isn't before.\n";
        my $before = $after;#set $before to be the new value after the update
        my $after = 0; #this will be updated in the next update
        sleep 1;
    }
}

When I run this, it claims that it is setting $before to $after in the else{}, but, in fact, $before remains 10, as it was set to before, and the program loops endlessly.

The script runs correctly when I remove the mys from inside else{}:

use strict;
use warnings;
my $after = 0;
my $before ="10";

until( $before == $after ) {
    #check again, which changes the value of $after.
    #Now....
    $after = "20"; 

    if($after == $before) {
        print "After is before. Moving out of until because all files are there!\n";
    }
    else {
        print "After isn't before.\n";
        $before = $after;#set $before to be the new value after the update
        $after = 0; #this will be updated in the next update
        sleep 1;
    }
}

Does this mean that $before defined as 'my $before' within the else is not the same variable as '$before' defined above it?

È stato utile?

Soluzione

When you write code, ALWAYS INDENT CORRECTLY. It's difficult to see how the code executes, and it also can hide errors when code is poorly indented. Also, always use white space and don't double up statements. 90% of programming is maintenance, so what little extra typing you do to make your code easy to understand saves a ton of time in maintaining it.

I've reinvented your code, so I could read it.


When you use my to declare a variable, you are declaring it as a lexically scoped. What this means is that it is defined in a limited context. This is ususally a good thing. It means variables disappear when you no longer need them. However, it also means that variables disappear when you need them.

my variables live in the block where they're defined. If the are defined inside a while/until loop, they live within that while loop. Once you exit the while, they go bye-bye. Same thing with an if statement or a for loop. In fact, if you just put curly braces, the my variable, if defined in those curly braces will lose it's definition once outside:

{
    my $foo = "bar";
}
print "$foo\n";   # Whoops, $foo is undefined!

If you need a variable to live outside of the loop, it needs to be defined outside of that loop:

my $odd_count = 0;
for my $number ( @number_list ) {
    if ( $number % 2 ) { 
        $odd_count++;
    }
}
print "There are $odd_count numbers in my list\n";

You can also end up redefining a variable if you redeclare it with my:

use warnings;
use strict;
use feature qw(say);

my $foo = "bar";
{    # New block!
     say "Initial value of \$foo: $foo";
     my $foo = "foo";   # Using "my" on $foo
     say "Changed value of \$foo: $foo";
}
say "Final value of \$foo: $foo";

If you run this, you'll get:

Initial value of $foo: bar
Changed value of $foo: foo
Final value of $foo: bar

That's because you've redeclared $foo inside the block, so you now have a new variable $foo that will cover the old value of $foo until the block ends. Once the block ends, the old$foo` variable is back, with its old value:

my $foo = "bar";
{    # New block!
     say "Initial value of \$foo: $foo";
     $foo = "foo";   # No "my" on $foo
     say "Changed value of \$foo: $foo";
}
say "Final value of \$foo: $foo";

If you run this, you'll get:

Initial value of $foo: bar
Changed value of $foo: foo
Final value of $foo: foo

In this case, I removed the my. Now when I say $foo = "foo";, I'm using the same $foo I defined outside the block, so once I leave the block, $foo will still have its old value.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top