Iai*_*der 9 perl named-parameters
根据我对支持该功能的语言的体验,使用命名参数而不是位置参数调用函数的程序更易于阅读和维护.
我认为Perl有这个功能,但它不适合我.
这是我正在使用的包裹的怪癖,还是我做错了?
我的第一个Perl项目是使用HTML :: TableExtract包从HTML标记中提取表数据并将其显示为文本.
以下代码设置解析器:
use strict;
use warnings;
use HTML::TableExtract;
my $markup = <<MARKUP;
<table>
<tr> <th>a</th> <th>b</th> <th>c</th> </tr>
<tr> <td>1</td> <td>2</td> <td>3</td> </tr>
<tr> <td>4</td> <td>5</td> <td>6</td> </tr>
</table>
MARKUP
my $parser = HTML::TableExtract->new() ;
$parser->parse($markup) ;
Run Code Online (Sandbox Code Playgroud)
该文件说,我可以使用输出转储到命令提示符tables_dump方法和使用参数$show_content和$col_sep控制输出格式:
tables_report([$show_content, $col_sep])返回一个字符串,汇总提取的表格及其深度和计数.可选择使用$ show_content标志,该标志将转储每个表的提取内容以及由$ col_sep分隔的列.默认$ col_sep是':'.
tables_dump([$show_content, $col_sep])与tables_report()相同,但将信息转储到STDOUT.
如果我按文档顺序传递位置参数,我得到我期望的输出:
$parser->tables_dump(1, '_') ;
Run Code Online (Sandbox Code Playgroud)
列由下划线而不是默认冒号分隔:
TABLE(0, 0):
a_b_c
1_2_3
4_5_6
Run Code Online (Sandbox Code Playgroud)
在Perl.com的高级子例程文章之后,我尝试传递包含参数名称和值的哈希,以阐明参数的含义:
$parser->tables_dump({show_content => 1, col_sep => '_'}) ;
Run Code Online (Sandbox Code Playgroud)
Perl不明白这一点.它忽略col_sep默认值的值和输出:
TABLE(0, 0):
a:b:c
1:2:3
4:5:6
Run Code Online (Sandbox Code Playgroud)
如果我不尝试更改分隔符,我会得到相同的输出:
$parser->tables_dump({show_content => 1}) ;
Run Code Online (Sandbox Code Playgroud)
即使我指定了无意义的参数名称,我也得到相同的输出:
$parser->tables_dump({tweedledum => 1, tweedledee => '_'}) ;
Run Code Online (Sandbox Code Playgroud)
我可以使用命名参数样式调用此函数,还是应该满足于位置?
在面向对象的Perl,第6章中非常好地解释了在Perl中传递的命名参数(即使使用默认值).这种样式非常重要,并且在对象构造函数中得到广泛使用.这就是他们的OO Perl书中解释的原因.
我将引用他们的两个例子:
# This is how you call a subroutine using named argument passing
interests(name => "Paul", language => "Perl", favourite_show => "Buffy");
# This is how you define the subroutine to accept named arguments
sub interests {
my (%args) = @_;
# This is how you capture named arguments and define
# defaults for the ones missing from a particular call.
my $name = $args{name} || "Bob the Builder";
my $language = $args{language} || "none that we know";
my $favourite_show = $args{favourite_show} || "the ABC News";
print "${name}’s primary language is $language. " .
"$name spends their free time watching $favourite_show\n";
}
Run Code Online (Sandbox Code Playgroud)
另一个给出定义默认值(在散列中)的方法的例子是:
my %defaults = ( pager => "/usr/bin/less", editor => "/usr/bin/vim" );
sub set_editing_tools {
my (%args) = @_;
# Here we join our arguments with our defaults. Since when
# building a hash it’s only the last occurrence of a key that
# matters, our arguments will override our defaults.
%args = (%defaults, %args);
# print out the pager:
print "The new text pager is: $args{pager}\n";
# print out the editor:
print "The new text editor is: $args{editor}\n";
}
Run Code Online (Sandbox Code Playgroud)
在 Perl.com 的 Advance Subroutines 文章之后,我尝试传递包含参数名称和值的哈希来阐明参数的含义:
该文章介绍了一种编写子例程的方法,以便它们接受命名参数的哈希引用。如果您调用的子程序未编写为接受该子程序,那么它将不知道如何正确处理它。
Run Code Online (Sandbox Code Playgroud)$parser->tables_dump({show_content => 1, col_sep => '_'}) ;Perl 不明白这一点。它忽略 col_sep 的值并使用默认值输出:
不想过于迂腐,但 Perl 很好地理解这一点。但是,tables_dump仅编写为接受标量参数列表。当您以这种方式调用它时,它会接收一个标量参数。该参数恰好是对哈希值的引用,但tables_dump不知道也不关心它,因此它使用该引用作为 的值$show_content。这可能相当于传递1for show_content,因为两者1和任何可能的引用都将在布尔上下文中评估为“true”,并且我假设它$show_content仅用作布尔值。
由于没有第二个参数,因此没有任何内容被分配给$col_sep,因此它使用默认分隔符,正如您所观察到的。