English 中文(简体)
Perl - 这些行为的范围/范围/环境是什么?
原标题:Perl - What scopes/closures/environments are producing this behaviour?

Given a root directory I wish to identify the most shallow parent directory of any .svn directory and pom.xml .

为实现这一目标,我确定了以下职能:

use File::Find;
sub firstDirWithFileUnder {
    $needle=@_[0];
    my $result = 0;
    sub wanted {
        print "	wanted->result is  $result 
";
        my $dir = "${File::Find::dir}";

        if ($_ eq $needle and ((not $result) or length($dir) < length($result))) {
            $result=$dir;
            print "Setting result:  $result 
";
        }
    }
    find(&wanted, @_[1]);
    print "Result:  $result 
";
    return $result;
}

因此:

    $svnDir = firstDirWithFileUnder(".svn",$projPath);
    print "	Identified svn dir:
	 $svnDir 
";
    $pomDir = firstDirWithFileUnder("pom.xml",$projPath);
    print "	Identified pom.xml dir:
	 $pomDir 
";

我无法解释两种情况:

  1. When the search for a .svn is successful, the value of $result perceived inside the nested subroutine wanted persists into the next call of firstDirWithFileUnder. So when the pom search begins, although the line my $result = 0; still exists, the wanted subroutine sees its value as the return value from the last firstDirWithFileUnder call.
  2. If the my $result = 0; line is commented out, then the function still executes properly. This means a) outer scope (firstDirWithFileUnder) can still see the $result variable to be able to return it, and b) print shows that wanted still sees $result value from last time, i.e. it seems to have formed a closure that s persisted beyond the first call of firstDirWithFileUnder.

有些人是否可以解释正在发生什么,并建议我如何在进入外层空间时适当重新确定<条码>(按美元/<>/代码”的价值?

最佳回答

使用<条码>警报,然后<条码>diagnostics生成这一有用的信息,包括一种解决办法:

可变的“价格”在-------第12条(第1条)中不予分摊。

(W closure) An inner (nested) named subroutine is referencing a lexical variable defined in an outer named subroutine.

When the inner subroutine is called, it will see the value of the outer subroutine s variable as it was before and during the first call to the outer subroutine; in this case, after the first call to the outer subroutine is complete, the inner and outer subroutines will no longer share a common value for the variable. In other words, the variable will no longer be shared.

This problem can usually be solved by making the inner subroutine anonymous, using the sub {} syntax. When inner anonymous subs that reference variables in outer subroutines are created, they are automatically rebound to the current values of such variables.


$result is lexically scoped, meaning a brand new variable is allocated every time you call &firstDirWithFileUnder. sub wanted { ... } is a compile-time subroutine declaration, meaning it is compiled by the Perl interpreter one time and stored in your package s symbol table. Since it contains a reference to the lexically scoped $result variable, the subroutine definition that Perl saves will only refer to the first instance of $result. The second time you call &firstDirWithFileUnder and declare a new $result variable, this will be a completely different variable than the $result inside &wanted.

页: 1

my $wanted = sub {
    print "	wanted->result is  $result 
";
    ...
};

并援引<代码>File:Find:find

find($wanted, $_[1])

此处,$wanted is a run-time declaration for a subroutine, and it has foundd with this reference to $result in each separate calls to &firstDirWithFile Under


<>Update: 该法典可证明具有启发性:

sub foo {
    my $foo = 0;  # lexical variable
    $bar = 0;     # global variable
    sub compiletime {
        print "compile foo is ", ++$foo, " ", $foo, "
";
        print "compile bar is ", ++$bar, " ", $bar, "
";
    }
    my $runtime = sub {
        print "runtime foo is ", ++$foo, " ", $foo, "
";
        print "runtime bar is ", ++$bar, " ", $bar, "
";
    };
    &compiletime;
    &$runtime;
    print "----------------
";
    push @baz, $foo;  # explained below
}
&foo for 1..3;

典型产出:

compile foo is 1 SCALAR(0xac18c0)
compile bar is 1 SCALAR(0xac1938)
runtime foo is 2 SCALAR(0xac18c0)
runtime bar is 2 SCALAR(0xac1938)
----------------
compile foo is 3 SCALAR(0xac18c0)
compile bar is 1 SCALAR(0xac1938)
runtime foo is 1 SCALAR(0xa63d18)
runtime bar is 2 SCALAR(0xac1938)
----------------
compile foo is 4 SCALAR(0xac18c0)
compile bar is 1 SCALAR(0xac1938)
runtime foo is 1 SCALAR(0xac1db8)
runtime bar is 2 SCALAR(0xac1938)
----------------

Note that the compile time $foo always refers to the same variable SCALAR(0xac18c0), and that this is also the run time $foo THE FIRST TIME the function is run.

<代码>&foo,push @baz,$foo最后一行列入本例,以便$foo 在<代码>&foo末收集的垃圾箱。 否则,第2和第3次运行时间<代码>$foo可指同一地址,尽管这些地址指的是不同的变量(每当申报变量时,记忆就会重新定位)。

问题回答

暂无回答




相关问题
Why does my chdir to a filehandle not work in Perl?

When I try a "chdir" with a filehandle as argument, "chdir" returns 0 and a pwd returns still the same directory. Should that be so? I tried this, because in the documentation to chdir I found: "...

How do I use GetOptions to get the default argument?

I ve read the doc for GetOptions but I can t seem to find what I need... (maybe I am blind) What I want to do is to parse command line like this myperlscript.pl -mode [sth] [inputfile] I can use ...

Object-Oriented Perl constructor syntax and named parameters

I m a little confused about what is going on in Perl constructors. I found these two examples perldoc perlbot. package Foo; #In Perl, the constructor is just a subroutine called new. sub new { #I ...

Where can I find object-oriented Perl tutorials? [closed]

A Google search yields a number of results - but which ones are the best? The Perl site appears to contain two - perlboot and perltoot. I m reading these now, but what else is out there? Note: I ve ...

热门标签