【问题标题】:What does @_ -1 mean in Perl?@_ -1 在 Perl 中是什么意思?
【发布时间】:2011-01-22 02:40:24
【问题描述】:

我正在尝试将 Perl 脚本翻译成 PHP,但我遇到了一些 Perl 问题。例如,@_ -1 是什么意思?以及如何用 PHP 编写它?

整个函数如下:

sub variance {
    my $sum = sum_squares (@_);
    my $deg = @_ - 1;
    return $sum/$deg;
}

好的,所有子程序如下:

sub mean { # mean of values in an array
  my $sum = 0 ;
  foreach my $x (@_) {
    $sum += $x ;
  }
  return $sum/@_ ;
}

sub sum_squares { # sum of square differences from the mean
  my $mean = mean (@_) ;
  my $sum_squares = 0 ;
  foreach my $x (@_) {
    $sum_squares += ($x - $mean) ** 2 ;
  }
  return $sum_squares ;
}

sub variance { # variance of values in an array
  my $sum_squares = sum_squares (@_) ;
  my $deg_freedom = @_ - 1 ;
  return $sum_squares/$deg_freedom ;
}

sub median { # median of values in an array
  my @sorted = sort {$a <=> $b} (@_) ;
  if (1 == @sorted % 2) # Odd number of elements
    {return $sorted[($#sorted)/2]}
  else                   # Even number of elements
    {return ($sorted[($#sorted-1)/2]+$sorted[($#sorted+1)/2]) / 2}
}

sub histogram { # Counts of elements in an array
  my %histogram = () ;
  foreach my $value (@_) {$histogram{$value}++}
  return (%histogram) ;
}

请多多包涵,因为这是我第一次接触 Perl。从我所看到的(测试)来看,在这种情况下,正确的答案是 David Dorward 的答案。关于这组子例程,我还有另一个问题是here

【问题讨论】:

  • 相等但不相等。写你想要的那个是明智的。如果您的意思是“比@_ 中的事物数量少一个”,请写@_ - 1。如果您的意思是“@_ 中的最后一个索引”,请写为 $#_
  • (从技术上讲,如果您使用已弃用且彻底邪恶的$[,两者可能甚至不相等。但不要那样做。)

标签: php perl arrays


【解决方案1】:

在这种情况下,@_ 是作为列表传递给子例程的参数。

在标量上下文中,它是该列表中的元素数。

所以如果你打电话:variance('a', 'b', 'c', 'd');$deg 将是 3。

【讨论】:

  • @_ 是一个数组,而不是一个列表。
  • 学究式:@_ 是一个数组,其中包含作为列表传递给子例程的参数。
【解决方案2】:

@_ 是传递给子程序的参数列表。当您在非标量上下文中使用它时,例如:

sum_squares (@_)

你得到了这个列表,所以大概会返回该列表中所有数字的平方和(但是请参阅下面的评论)。

在标量上下文中使用时,您会得到长度,因此在您的情况下,它将是 $@ 函数列表中的项目数。

所以你的方差函数可能是(我说可能是因为我无法访问sum_squares 源代码)计算:

variance = arr[0]^2 + arr[1]^2 + ... + arr[N-1]^2
           --------------------------------------
                            N - 1

关于传入函数的值数组。

我不得不说我对方差的理解与此不一致(尽管我已经有一段时间没有做任何统计数据了)。我很确定它应该涉及值和平均值之间的差异的平方和,而不是值本身。我怀疑sum_squares 内部发生的事情比它简单的名字所暗示的要多。

【讨论】:

    【解决方案3】:

    这是传递给variance 子例程的参数的数量减去一(或@_ 数组中最后一个元素的索引)。 @_ 在这里用于标量上下文。

    【讨论】:

      【解决方案4】:

      就像已经说过的,它是传递给函数的参数数组。它在 PHP 中是等价的

      整个函数是

      function variance() {
          $sum = sum_squares(func_get_args());
          $deg = func_num_args() - 1;
          return $sum/$deg;
      }
      // echo variance(1,2,3,4,5); // 13.75 (55/4)
      

      对于sum_squares,PHP 中没有原生函数。假设它符合名称的含义,例如将每个参数提高到 2 的幂,然后对结果求和,您可以将其实现为

      function sum_squares(array $args) {
          return array_reduce(
              $args, create_function('$x, $y', 'return $x+$y*$y;'), 0
          );
      }
      // echo sum_squares( array(1,2,3,4,5) ); // 55
      

      如果您使用的是 PHP5.3,请将 create_function 替换为正确的 lambda

      【讨论】:

      • 这个函数会抛出一个错误。 (见上面的整个代码)
      • @Alex 什么错误?调用未定义的函数 sum_squares?当然可以。这是一个用户态函数,你必须在某个地方定义它。有关可能的实施,请参阅上面的更新。
      • @Gordon 是的,那个。我定义了它。这是 php 代码: function mean($array) { return array_sum($array) / count($array); } 函数 sum_squares($array) { $sum = 0; $mean = mean($array); foreach ($array as $key => $val) { $sum += pow($val - $mean, 2); } 返回$总和;使用这些函数,您的方差函数版本会抛出错误。
      • @Alex 如果您能添加错误消息,我将不胜感激。只是说它不起作用或抛出错误并不能说明可能出了什么问题。当我使用你在上面评论中给出的函数时,variance(1,2,3,4,5) 将返回 2.5,没有错误。
      • 没错,我的错!这是:致命错误:第 20 行的 Document 中不支持的操作数类型。第 20 行是这样的:$sum += pow($val - $mean, 2);
      【解决方案5】:

      @_ 是 sub 的传入参数,但在标量上下文中引用的是参数的数量。

      在 php 中会是这样的:

      function variance() {
          $arguments = func_get_args();
          $sum = sum_squares($arguments);
          $deg = sizeof($arguments);
          return $sum/$deg;
      }
      

      【讨论】:

        【解决方案6】:

        为了补充其他答案,@_Special Variable 在免费的官方 Perl 在线文档(连同其他变量)中有描述:

        在子程序中,数组@_ 包含传递给它的参数 子程序。请参阅 perlsub。

        【讨论】:

          【解决方案7】:

          在函数@_ 中将有传递给函数的函数参数列表。 实际上,当我们尝试将列表值分配给标量时,它将分配数组的长度。 这里 -1 用于访问 @_ 数组的最后一个元素

          子测试 { 我的 $count = @_ ; # 现在它将分配函数参数的数量 # 因为我们试图分配为标量。 >打印“输出:$count\n”; # 输出:4 ($count ) = @_ # 现在它将分配函数的第一个元素 打印“输出:$count\n”; # 输出:10 # 因为我们试图赋值为列表值,所以,列表只作为一个变量。 # 所以,第一个元素被分配。 } &test ( 10,20,30,40 ) ;

          【讨论】:

            猜你喜欢
            • 2010-12-28
            • 2018-03-05
            • 2010-11-05
            • 2023-03-25
            • 1970-01-01
            • 1970-01-01
            • 2019-03-18
            • 2020-05-21
            • 1970-01-01
            相关资源
            最近更新 更多