Perl 如何在不牺牲性能的情况下保持良好的代码组织?

Perl 如何在不牺牲性能的情况下保持良好的代码组织?,perl,performance,code-organization,Perl,Performance,Code Organization,我同意这样一种观点,即在使用变量之前不应该初始化变量。如果一个变量是由代码使用的,那么它就更容易记住它所代表的内容,并且它减少了变量在初始化和正确使用之间被误用的可能性 当该变量的使用在一两个循环中时,问题就出现了。然后,初始化的成本会成倍增加,并可能开始影响性能 在Perl中(或通常情况下,视情况而定),它们是否有任何巧妙的小技巧,允许您将变量的初始化放在循环中,但它只能在第一次通过时初始化 我想到了这样的事情: my $variable = undef; while ($outer_loop

我同意这样一种观点,即在使用变量之前不应该初始化变量。如果一个变量是由代码使用的,那么它就更容易记住它所代表的内容,并且它减少了变量在初始化和正确使用之间被误用的可能性

当该变量的使用在一两个循环中时,问题就出现了。然后,初始化的成本会成倍增加,并可能开始影响性能

在Perl中(或通常情况下,视情况而定),它们是否有任何巧妙的小技巧,允许您将变量的初始化放在循环中,但它只能在第一次通过时初始化

我想到了这样的事情:

my $variable = undef;
while ($outer_loop) {
    while ($inner_loop) {
       $variable = $variable || 'initial_value'
    }
}
注意:这意味着
$variable
不会在循环中重新分配

现在也许是我,但这似乎有点不雅

所以,我的问题是:有没有更整洁的方法来做到这一点,或者我只是需要克服自己,在代码组织上妥协,还是接受上面的“不雅观”解决方案

当该变量的使用在一两个循环中时,问题就出现了。然后,初始化的成本会成倍增加,并可能开始影响性能

是吗?你量过了吗?如果您的
$variable
应用于两个循环中的代码,那么我将按如下方式编写您的循环:

my $variable = 'initial_value';
while ($outer_loop) {
    while ($inner_loop) {
       # ...
    }
}
这样,读者就知道
$variable
用于下面的代码部分,以及它的初始值是什么。在代码片段中,读者必须在循环的深处找到实际的初始值


此处不太可能存在性能问题,但如果性能是一个关键因素,则应始终测量性能。

要解决注释中的问题(变量在函数中计算):

  • 优化这类逻辑的标准技术称为(该函数的)记忆化。在其他方法中,Perl有
    Memoize
    模块,或者您可以自己做

      use Memoize;
      memoize('slow_function');
      while ($outer_loop) {
          while ($inner_loop) {
              my $variable = slow_function(arguments);
          }
      }
    
  • 此外,如果函数在整个循环中总是产生100%相同的值(根据设计),只需在循环之前在语句中初始化变量,就可以实现糟糕的记忆

    如果您有一个3页长的循环(例如,与循环内部相比,在循环之前进行初始化是一个可读性问题),那么您的编码问题比初始化行的位置更大,首先需要重新考虑代码

    另一方面,如果将变量放在循环之前的唯一问题是它会破坏“此变量仅用于此循环”的可读性上下文,则可以通过以下方法轻松解决:

    • 拥有文档化的代码-可以相应地命名变量,或者在初始化行中添加注释,或者两者兼而有之

    • 或者,通过为_next_loop=long_func()命名一个变量,比如
      my$default_value_
      ,并在循环内部实际创建一个从该变量初始化的本地循环变量:
      my$loop\u var=$default\u value\u for\u next\u循环

另外,就您自己的方法而言(
$variable=$variable | | |‘initial_value’;
);
我个人觉得这绝对优雅易读,但是!!!我很确定它的性能实际上比直接的
$variable=$default\u value\u for\u next\u循环差,因为它有一个条件语句而不是直接赋值。但如果没有基准测试,我无法确定。

我认为你的指导方针有点太过分了。阻止变量误用的最佳方法是将其声明延迟到需要之前。(因此将其限制在尽可能小的词法范围内。)延迟初始化并不能防止误用;它只是为某些人创造了一个机会,他们可以使用未定义的值,用自己的值抢占初始化,或者将变量用于完全无关的目的

如果变量需要初始/默认值,则应尽可能将其作为声明的一部分。这表明变量有一个起始值

my $x = 1;
my $y = f($x);
延迟初始化意味着没有初始值。如果没有,或者您无法提前确定,那么这很好,但是您会牺牲清晰度,在以后的时间里偷偷添加一个
$var/='value'

对于需要在循环迭代中保留其值的变量,必须在循环外部声明它们。有时,我将循环包装在一个额外的块中,以防止这些变量泄漏到以下代码中:

{
    my $i = 5;
    for (1 .. 10) {
        say $i++;
    }
}

它确实。。。这不是一个简单的任务;该值是通过函数调用生成的。我同意,一般来说,衡量价值创造的成本,看看它是否重要可能更好,但是我仍然有兴趣看看是否有其他技术可以/通常/被应用。您希望以多大的频率接近代码片段,而不深入循环调用初始化函数?在循环顶部初始化变量的代码仍在执行相同的工作量,只是顺序不同。而且,您不必每次通过内部循环检查变量是否已初始化。谢谢。我将仔细考虑这些选项,找出哪一个更适合我的特定模块。。。值得深思。