Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl variables scoping

Tags:

scope

perl

I wanted to remove duplicate values from an array with this approach. The duplicates removal have to be executed inside a loop. Here is a minimal example that demonstrates the problem that I encountered:

use strict;

for (0..1){
    my %seen;
    sub testUnique{
        return !$seen{shift}++;
    }

    my $res = testUnique(1);

    if($res){
        print "unique\n";
    }else{
        print "non-unique\n";
    }
}

I define the %seen hash inside a loop, so I would expect it to be defined only during a single iteration of the loop. The result of the above code is however:

unique
non-unique

With some debug prints, I found out that the value of %seen is preserved from one iteration to another.

I tried a trivial

for (0..1){
    my %seen;
    $seen{1}++;
    print "$seen{1}\n";
}

And this one worked as expected. It printed:

1
1

So, I guess the problem is with inner function testUnique. Can somebody explain me what is going on here?

like image 431
jutky Avatar asked Feb 11 '26 03:02

jutky


1 Answers

Your testUnique sub closes over the first instance of %seen. Even though it is inside the for loop, the subroutine does not get compiled repeatedly.

Your code is compiled once, including the part that says initialize a lexically scoped variable %hash right at the top of the for loop.

The following will produce the output you want, but I am not sure I see are going down this path:

#!/usr/bin/env perl

use warnings;
use strict;

for (0..1){
    my %seen;
    my $tester = sub {
        return !$seen{shift}++;
    };

    print $tester->(1) ? "unique\n" : "not unique\n";
}
like image 79
Sinan Ünür Avatar answered Feb 14 '26 14:02

Sinan Ünür



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!