Perl中的静态局部变量

Cha*_*les 14 perl scope

我正在寻找有关Perl最佳实践的建议.我写了一个脚本,它有一个复杂的正则表达式:

my $regex = qr/complicated/;

# ...

sub foo {
  # ...

  if (/$regex/)
  # ...
}
Run Code Online (Sandbox Code Playgroud)

where foo是一个经常被调用的函数,并且$regex不在函数之外使用.处理这种情况的最佳方法是什么?我只希望它被解释一次,因为它漫长而复杂.但是将它放在全球范围内似乎有点可疑,因为它仅用于该子目录.是否有合理的方法将其声明为静态?

另一个可能不合理的全球性问题也出现了类似的问题.它读取当前日期和时间并适当地格式化它.这也被多次使用,并且仅在一个功能中使用.但是在这种情况下更重要的是它不能重新初始化,因为我希望日期时间的所有实例在给定的脚本调用中是相同的,即使在执行期间分钟翻转.

目前我有类似的东西

my ($regex, $DT);

sub driver {
  $regex = qr/complicated/;
  $DT = dateTime();
  # ...
}

# ...

driver();
Run Code Online (Sandbox Code Playgroud)

至少略微隔离它.但也许有更好的方法.

再说一遍:我正在寻找正确的方法,以遵循最佳实践和Perl习语.性能很好,但如果我不能拥有所有东西,那么可读性和其他需求就会优先考虑.

hob*_*bbs 25

如果您使用的是perl 5.10+,请使用state变量.

use feature 'state';
# use 5.010; also works

sub womble {
    state $foo = something_expensive();
    return $foo ** 2;
}
Run Code Online (Sandbox Code Playgroud)

只会打something_expensive一次电话.

如果你需要使用旧的perls,那么在外部作用域中使用一个词法变量,并使用一对额外的大括号:

{
    my $foo = something_expensive();
    sub womble {
        return $foo ** 2;
    }
}
Run Code Online (Sandbox Code Playgroud)

$foo不会泄漏给除了之外的任何人womble.

  • `state`是在5.10中引入的,而不是5.12中引入的.([Dev release 5.9.4](http://perldoc.perl.org/perl594delta.html#state%28%29-variables),实际上.) (3认同)
  • 使用词法范围变量的技巧只有在执行变量赋值时才有效.如果您通常将子例程放在主文件的底部,则只有在程序流到达时才会执行赋值. (2认同)

ike*_*ami 15

模式中是否有插值?如果不是,则无论qr //执行多少次,模式都只会被编译一次.

$ perl -Mre=debug -e'qr/foo/ for 1..10' 2>&1 | grep Compiling | wc -l
1

$ perl -Mre=debug -e'qr/foo$_/ for 1..10' 2>&1 | grep Compiling | wc -l
10
Run Code Online (Sandbox Code Playgroud)

即使存在插值,只有在插值变量发生变化时才会编译模式.

$ perl -Mre=debug -e'$x=123; qr/foo$x/ for 1..10;' 2>&1 | grep Compiling | wc -l
1

$ perl -Mre=debug -e'qr/foo$_/ for 1..10' 2>&1 | grep Compiling | wc -l
10
Run Code Online (Sandbox Code Playgroud)

否则,你可以使用

{
   my $re = qr/.../;
   sub foo {
      ...
      /$re/
      ...
   }
}
Run Code Online (Sandbox Code Playgroud)

要么

use feature qw( state );
sub foo {
   state $re = qr/.../;
   ...
   /$re/
   ...
}
Run Code Online (Sandbox Code Playgroud)