gpt4 book ai didi

perl - 如何禁用当前范围内未使用变量的优化?

转载 作者:行者123 更新时间:2023-12-02 18:33:49 25 4
gpt4 key购买 nike

例如我有代码:

my $x =  77;

sub test {
$DB::single = 1;
1;
}
test();

如果我使用 -d 标志运行此脚本:perl -d test.pl,则该脚本执行将在断点处停止(第 5 行)。从断点开始,$x 变量可见。如果我尝试通过调试器查看其值,它将是未定义的。如果我像下面这样改变我的程序:

sub test {
print $x;
$DB::single = 1;
1;
}
test();

然后 $x 可见。

是否有任何 Perl 调试器选项允许禁用当前范围内未使用的变量的优化?

最佳答案

没有。

这不是优化;而是优化。该变量已创建,但当您决定检查它时,它已不再存在,因为执行已达到其范围。

如果子进程因为使用 $x 而看到 $x,这是因为子进程捕获了 $x。 Subs 仅捕获他们需要捕获的变量。不必要的捕获可能会产生非常有害的影响(因为析构函数不会在预期时被调用)。

除非逐个变量地进行,否则没有办法告诉 Perl 做其他事情。


首先,您发布的代码没有出现您所描述的问题。

$ perl -d a.pl

Loading DB routines from perl5db.pl version 1.55
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

main::(a.pl:1): my $x = 77;
DB<1> r
main::test(a.pl:5): 1;
DB<1> x $x
0 77
DB<2> q

但是如果代码是模块的一部分,就会遇到这个问题。

Foo.pm:

package Foo;

my $x = 77;

sub test {
$DB::single = 1;
1;
}

1;
$ perl -d -I. -e'use Foo; Foo::test()'

Loading DB routines from perl5db.pl version 1.55
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

main::(-e:1): use Foo; Foo::test()
DB<1> r
Foo::test(Foo.pm:7): 1;
DB<1> x $x
0 undef
DB<2> q

将来,请确保您发布的代码确实能够说明您声称的问题。


假设你有

{
my $x = 77;
}

CORE::say $x;

这行不通,对吧?这不是因为优化 - 创建了 $x,并为其分配了 77 - 这是因为当词法包含它的范围已退出。

现在让我们考虑以下问题:

{
my $x = 77;
sub get_x { $x }
}

CORE::say get_x();

这会以某种方式打印77。这怎么可能?我刚刚解释说 $x 在到达最后一行之前就不再存在。好吧,如果不是 get_x 捕获了它,它就会不复存在。我们说 get_xclosure$x 继续存在,但仅在闭包中。

不用说,捕获变量需要花费精力(CPU和内存),因此只捕获需要捕获的变量。不捕获不需要捕获的变量不是优化;它只是没有执行未请求的工作。


这和你的问题有什么关系?嗯, block (花句)并不是唯一创建词法范围的东西。 Perl 加载的文件在新的词法作用域中执行。

换句话说,上面失败的测试大致相当于

BEGIN {
package Foo;

my $x = 77;

sub test {
$DB::single = 1;
1;
}

$INC{"Foo.pm"} = 1;
}

use Foo;
Foo::test();

归结为

{
my $x = 77;

sub test {
$DB::single = 1;
1;
}
}

test();

鉴于上述情况,以下问题是有效提出的问题:

Is there a way to tell Perl to have subs capture variables it doesn't use?

答案是否定的。

只有捕获的变量和仍然存在的变量在调用时可供子程序使用。捕获不必要的变量会导致变量持续存在的时间比预期长,这意味着析构函数不会在预期时被调用。

除非在逐个变量的基础上(例如,通过将 $x if 0; 添加到 sub),否则无法告诉 Perl 执行其他操作。


附录:您可能会在使用 eval EXPR 时遇到类似的问题。

$ perl -e'
my $x = 77;
sub test {
return eval($_[0]);
}

printf "[%s]\n", test(q{$x});
'
[77]

$ perl -e'
{
my $x = 77;
sub test {
return eval($_[0]);
}
}

printf "[%s]\n", test(q{$x});
'
[]

$ perl -e'
{
my $x = 77;
sub test {
$x if 0;
return eval($_[0]);
}
}

printf "[%s]\n", test(q{$x});
'
[77]

附录:捕获非常有用!他们使回调变得轻而易举。

sub any {
my $callback = shift;
for (@_) {
return 0 if $callback->();
}

return 1;
}

my %bad = map { $_ => 1 } qw( foo bar );

die if any(sub { $bad{$_} }, @args); # Captures %bad

关于perl - 如何禁用当前范围内未使用变量的优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61102897/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com