Perl是否支持函数调用中的命名参数?

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)

我可以使用命名参数样式调用此函数,还是应该满足于位置?

Seg*_*nku 11

Perl本身不支持命名参数,但是可以设计函数来接受命名参数(作为散列或hashref).这取决于它们如何实现它的函数的作者.您需要提供函数期望的参数,否则您将获得意外结果.


Ahm*_*sar 6

面向对象的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)


Dav*_*man 4

在 Perl.com 的 Advance Subroutines 文章之后,我尝试传递包含参数名称和值的哈希来阐明参数的含义:

该文章介绍了一种编写子例程的方法,以便它们接受命名参数的哈希引用。如果您调用的子程序未编写为接受该子程序,那么它将不知道如何正确处理它。

$parser->tables_dump({show_content => 1, col_sep => '_'}) ;
Run Code Online (Sandbox Code Playgroud)

Perl 不明白这一点。它忽略 col_sep 的值并使用默认值输出:

不想过于迂腐,但 Perl 很好地理解这一点。但是,tables_dump仅编写为接受标量参数列表。当您以这种方式调用它时,它会接收一个标量参数。该参数恰好是对哈希值的引用,但tables_dump不知道也不关心它,因此它使用该引用作为 的值$show_content。这可能相当于传递1for show_content,因为两者1和任何可能的引用都将在布尔上下文中评估为“true”,并且我假设它$show_content仅用作布尔值。

由于没有第二个参数,因此没有任何内容被分配给$col_sep,因此它使用默认分隔符,正如您所观察到的。