这两个 eval 之间的区别是否用常量折叠来解释? [英] Is the difference between these two evals explained with constant folding?

查看:65
本文介绍了这两个 eval 之间的区别是否用常量折叠来解释?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定这两个仅改变 Module::FOO()FOO() 的评估.

Given these two evals which only change Module::FOO() and FOO().

# Symbols imported, and used locally.
eval qq[ 
  package Foo$num;
  Module->import();
  my \$result = Module::FOO() * Module::FOO();
] or die $@;

# Symbols imported, not used locally referencing parent symbol.
eval qq[ 
  package Foo$num;
  Module->import();
  my \$result = FOO() * FOO();
] or die $@;

为什么顶部块占用显着更少的空间?脚本和输出复制如下,

why would the top block take up substantially less space? The script and output are reproduced below,

package Module {
  use v5.30;
  use warnings;
  use constant FOO => 42; 
  use Exporter 'import';
  our @EXPORT = ('FOO');
}


package main {
  use v5.30;
  use autodie;
  use warnings;

  $|=1;
  say "Our PID is $$";

  for my $num ( 0..1e5 ) { 
    eval qq[ 
      package Foo$num;
      Module->import();
      my \$result = Module::FOO() * Module::FOO();
    ] or die $@;
    eval qq[
      package Foo$num;
      Module->import();
      my \$result = FOO() * FOO();
    ] or die $@;
  }

  say "DONE";

  _debug();

}

sub _debug {
  open my $fh, "<", "/proc/$$/status";
  while ( <$fh> ) { 
    next unless /Rss/;
    print;
  }
}

结果

包(命名空间)限定

RssAnon:      78896 kB
RssFile:       5220 kB
RssShmem:         0 kB

本地进口

RssAnon:     168180 kB
RssFile:       5496 kB
RssShmem:         0 kB

推荐答案

这是 Perl 内部不断折叠的结果.这可以通过 irc.freenode.net/#perl 上的 haarg 中的以下示例来演示,

This is a result of the constant folding inside of Perl. This can be demonstrated with the following example from haarg on irc.freenode.net/#perl,

use strict;
use warnings;

package Module {
  use constant FOO => 42;
  use Exporter 'import';
  our @EXPORT = ('FOO');
}

my $subs = {
  loc => sub {
    package Foo;
    Module->import();
    my $result = FOO() * FOO();
  },
  fq => sub {
    package Foo;
    Module->import();
    my $result = Module::FOO() * Module::FOO();
  },
};

use Data::Dumper;
$Data::Dumper::Deparse = $Data::Dumper::Indent = 1;
print Dumper($subs);

这将导致,

$VAR1 = {
  'loc' => sub {
      package Foo;
      use warnings;
      use strict;
      'Module'->import;
      my $result = FOO() * FOO();
  },
  'fq' => sub {
      package Foo;
      use warnings;
      use strict;
      'Module'->import;
      my $result = 1764;
  }
};

你可以看到其中一个有,

You can see one of them has,

my $result = FOO() * FOO();

虽然对方有,

my $result = 1764;

如果模块被声明并且导入是在编译器阶段(在子编译的情况下)或在字符串评估的情况下在执行之前完成,你可以得到常量折叠,就像这样

You can get constant folding in both if the module is declared and the import is done in the compiler phase (in the case of a sub compilation), or before the execution in the case of a stringy-eval, like this

BEGIN {

    package Module {
      use constant FOO => 42;
      use Exporter 'import';
      our @EXPORT = ('FOO');
    }
    package Foo { Module->import() }

}

这篇关于这两个 eval 之间的区别是否用常量折叠来解释?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆