Perl - 将参数作为散列键值对问题传递给子例程

标签 perl hash subroutine

我必须将两个引用作为参数传递给子例程(buildRanges)作为哈希键值对,如下所示

例子:

@array = (“0A0”, “005”, “001”, “004”, “0BC”, “004”, “002”, “001”);
@ranges = ();
$numRanges = buildRanges(VALUES => \@array, REF_RANGES=>\@ranges);

我的问题是
1. 上面子程序调用的语法是否正确?
2. VALUES 和 REF_RANGES 是什么?

坦率地说,我无法理解子程序调用,但我被告知只能使用该调用。

谢谢。

KK

最佳答案

说明

是的。这种语法对于 Perl 来说是正确且惯用的。让我们剖析您的函数调用的所有部分——很可能您已经知道部分解释。

准备:您输入的数据

@array = (“0A0”, “005”, “001”, “004”, “0BC”, “004”, “002”, “001”);
@ranges = ();
# \@array and \@ranges are now normal scalar references.

我希望你理解数组引用的概念。如果没有,请阅读 perlreftutperllol .实际上,这不会影响您询问的调用语法。顺便说一句,你可能还写过:
$array_ref=[“0A0”, “005”, “001”, “004”, “0BC”, “004”, “002”, “001”];
$range_ref=[];

$numRanges = buildRanges(VALUES => $array_ref, REF_RANGES=> $range_ref);

函数调用

在 Perl 中,箭头运算符 => 就像一个普通的逗号一样工作(有一个我们稍后讨论的小副作用)。以下调用完全相同:
$numRanges = buildRanges(VALUES => $array_ref, REF_RANGES => $range_ref);
$numRanges = buildRanges("VALUES", $array_ref, "REF_RANGES", $range_ref);

因此,您只需使用四个参数调用函数 buildRanges:两个常量字符串和两个数组引用。您注意到单词 VALUES 已更改为常量字符串“VALUE”;这同样适用于 REF_RANGES 一词。这是一条特殊规则:在箭头 => 之前和大括号 {} 内,普通标识符会被默默地转换为字符串。我们在下面再次看到这一点。但其他表达式如 $a => $b 保持原样,这里不会发生对字符串的静默转换。

您可能会问为什么 Perl 会这样做?这是语法糖 : => 操作符没有它你就不能做任何事情。但是对于有经验的 perl 程序员来说,KEY => $value 格式看起来比 "KEY", $value 更清晰。

函数定义

函数 buildRanges 的定义可能如下所示(我们在解释中使用它):
sub buidRanges { my(%info)=@_; 
  my $values    = $info{VALUES};
  my $ref_ranges= $info{REF_RANGES};
  my $special_feature = $info{SPECIAL_FEATURE}; # explained below
  if($special_feature) { ... return special_result; }
  ... process $values and $ref_ranges ... return $numRanges.
}

对于您的输入数据,以下四行中的每一行都具有相同的效果:
my(%info)=@_;                                          # the actual code
my(%info)=(VALUES => \@array, REF_RANGES=> \@ranges ); # what this does

my %info; $info{"VALUES"}=\@array; $info{"REF_RANGES"}=\@ranges; 
my %info; $info{ VALUES }=\@array; $info{ REF_RANGES }=\@ranges; 

基本上,输入数据被转换为允许访问每个参数的散列。函数调用中的常量字符串成为散列键。

选择您理解的一行并将其与其他行进行比较:它们做同样的事情。看 perldsc更多解释。

请注意,@_ 是输入参数的数组,在我们的例子中
@_ = ( VALUES => \@array, REF_RANGES=> \@ranges); 
@_ = ("VALUES",  \@array,"REF_RANGES", \@ranges);  # without syntactic sugar

您可能已经注意到 $info{VALUES} 等价于 $info{"VALUES"} -- 同样,这是语法糖,如上所述。

在我们假设的实现中,我们从哈希中提取输入数据:
 my $values     = $info{VALUES};       # i.e:  my $value      = \@array;
 my $ref_ranges = $info{REF_RANGES};   # i.e:  my $ref_renges = \@ranges;

现在,我们的函数实现可以处理输入数据。

为什么我们这样做不简单? --- 命名参数

到目前为止,我们可以更简单地实现类似的效果:
$numRanges = buildRanges($array_ref, $range_ref);  # simpler function call

sub buidRanges { my($values, $ref_ranges)=@_; 
  ... process $values and $ref_ranges ... return $numRanges.
}

这很可能是您已经很了解的编程风格。

那么:为什么要让某些 Perl 程序员变得更复杂(而且速度也慢得多)?
答案是:它更灵活,也更能自我记录。

为了更清楚地说明这一点,我在我们的函数定义中添加了一个 SPECIAL_FEATURE。现在,该函数也可以这样调用:
$numRanges = buildRanges(VALUES => \@array, SPECIAL_FEATURE=> "infinite ranges");

实现的函数可以告诉我们请求的是 SPECIAL_FEATURE 并且没有提供 REF_RANGES。

在一些高级函数中,您有很多有时(但并非总是)有用的额外功能,因此让调用者决定使用哪些功能以及不使用哪些功能是很有意义的。在这里,命名参数就派上用场了。

当然,我不能告诉你你的识别器识别了哪些特殊功能
buildRanges 函数 --- 您需要查看其实现或询问告诉您使用它的人。也有可能,作为一般约定,某些项目中的所有高级函数都使用这种调用方式,即使其中一些不提供太多特殊功能。

关于Perl - 将参数作为散列键值对问题传递给子例程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1825300/

相关文章:

arrays - 2个哈希数组之间的算术运算

c++ - C++ 中的 "Decrypt"MD5

c++ - 为什么我的用于删除重复字符的 c++14 程序在输出中给出了额外的字符?

function - 如何在 Perl 中检查函数参数是字符串还是数组

performance - Fortran - 函数与子程序性能

FORTRAN 中子程序的指针

perl - 我可以使用一个模块,然后卸载它以缩小 Optree 吗?

perl - 不匹配(在正则表达式中;由 <-- HERE 在 m/( <-- HERE 错误 perl

regex - 在文本文件中查找非空字段的索引

perl - 从 Perl 脚本内部在 alpine linux 上的 zsh 上获取 `Can' t exec "command"` 错误