jac*_*ter 16 variables perl local
我查了几个处理这个警告的答案,但他们也没有帮助我,也没有真正理解Perl在这里做的事情.这就是我想要做的事情:
sub outerSub {
my $dom = someBigDOM;
...
my $otherVar = innerSub();
return $otherVar;
sub innerSub {
my $resultVar = doStuffWith($dom);
return $resultVar;
}
}
Run Code Online (Sandbox Code Playgroud)
基本上,我有一个存储在$ dom中的大DOM对象,如果可能的话我不想在堆栈中传递.在outerSub中,正在发生需要来自innerSub的结果的东西.innerSub需要访问$ dom.当我这样做时,我收到这个警告"变量$ dom将不会保持共享".
我不明白的是:
这个警告对我有疑虑吗?我的逻辑会在这里运作还是会发生奇怪的事情?
如果它不能按预期工作:是否可以这样做?使局部变量对嵌套子变得可见?或者将它作为参数传递更好?或者声明一个"我们的"变量是否更好?
如果我将它作为参数推送,整个对象及其所有数据(可能有几个MB)是否会被推入堆栈?或者我可以传递类似参考的东西?或者Perl是否将该参数作为参考单独处理?
在"变量$ foo将不会保持共享"Perl中的警告/错误在调用子例程时,有人会谈论一个匿名子,这将使这成为可能.我不明白它是如何工作的,从来没有使用过这样的东西.
我根本不理解这个解释(可能导致英语不是我的第一语言):"当调用内部子程序时,它将看到外部子程序变量的值,就像它在第一次调用外部子程序之前和期间一样. ;在这种情况下,在第一次调用外部子程序完成后,内部子程序和外部子程序将不再共享变量的公共值.":
"对外部子程序的第一次调用是完整的是什么意思?"
我的意思是:首先我称之为外部子程序.外部子调用内部子.外子当然还在运行.一旦外部子完成,内部子也将完成.那么当内部子已经完成时,这仍然适用于什么呢?那么"第一次"召唤呢?什么时候发生"第二次"通话......对不起,这个解释让我感到困惑.
对不起,有很多问题.也许有人至少可以回答其中一些问题.
yst*_*sth 16
简而言之,调用第二个及以后的outerSub将具有与innerSub使用的$ dom变量不同的$ dom变量.你可以通过这样做解决这个问题:
{
my $dom;
sub outerSub {
$dom = ...
... innerSub() ...
}
sub innerSub {
...
}
}
Run Code Online (Sandbox Code Playgroud)
或通过这样做:
sub outerSub {
my $dom = ...
*innerSub = sub {
...
};
... innerSub() ...
}
Run Code Online (Sandbox Code Playgroud)
或这个:
sub outerSub {
my $dom = ...
my $innerSub = sub {
...
};
... $innerSub->() ...
}
Run Code Online (Sandbox Code Playgroud)
所有变量最初都是预先分配的,而innerSub和outerSub共享相同的$ dom.当你离开范围时,perl会遍历在范围中声明的词法变量并重新初始化它们.因此,当第一次调用outerSub完成时,它会得到一个新的$ dom.因为命名的subs是全局的东西,innerSub不受此影响,并且一直引用旧的$ dom.因此,如果第二次调用outerSub,则其$ dom和innerSub的$ dom实际上是单独的变量.
因此,将声明移出outerSub或使用匿名子(在运行时新近绑定到词法环境)可以解决问题.
您需要有一个匿名子例程来捕获变量:
my $innerSub = sub {
my $resultVar = doStuffWith($dom);
return $resultVar;
};
Run Code Online (Sandbox Code Playgroud)
例:
sub test {
my $s = shift;
my $f = sub {
return $s x 2;
};
print $f->(), "\n";
$s = "543";
print $f->(), "\n";
}
test("a1b");
Run Code Online (Sandbox Code Playgroud)
得到:
a1ba1b
543543
Run Code Online (Sandbox Code Playgroud)
如果您想最小化传递参数给 subs 的大小,请使用 Perl 引用。缺点/功能是 sub 可以更改引用的参数内容。
my $dom = someBigDOM;
my $resultVar = doStuffWith(\$dom);
sub doStuffWith {
my $dom_reference = shift;
my $dom_contents = $$dom_reference;
#...
}
Run Code Online (Sandbox Code Playgroud)