13

この機能をサポートする言語に関する私の経験では、位置パラメーターではなく名前付きパラメーターを使用して関数を呼び出すプログラムの方が、読みやすく、維持しやすいです。

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) ;

ドキュメントには、メソッドを使用してコマンドプロンプトに出力をダンプし、tables_dumpパラメーター$show_contentを使用$col_sepして、出力形式を制御できると記載されています。

tables_report([$show_content, $col_sep])

抽出されたテーブルをその深さと数とともに要約した文字列を返します。オプションで、各テーブルの抽出されたコンテンツと、$col_sep で区切られた列をダンプする $show_content フラグを受け取ります。デフォルトの $col_sep は ':' です。

tables_dump([$show_content, $col_sep])

STDOUT に情報をダンプする以外は、tables_report() と同じです。

位置パラメーターと名前付きパラメーターを使用した呼び出し

ドキュメントの順序で位置パラメーターを渡すと、期待どおりの出力が得られます。

$parser->tables_dump(1, '_') ;

列はデフォルトのコロンの代わりにアンダースコアで区切られます:

TABLE(0, 0):
a_b_c
1_2_3
4_5_6

Perl.com のAdvance Subroutines の記事に従って、パラメーターの意味を明確にするために、パラメーター名と値を含むハッシュを渡そうとしました。

$parser->tables_dump({show_content => 1, col_sep => '_'}) ;

Perl はこれを理解していません。の値を無視col_sepし、デフォルト値で出力します。

TABLE(0, 0):
a:b:c
1:2:3
4:5:6

セパレーターを変更しないと、同じ出力が得られます。

$parser->tables_dump({show_content => 1}) ;

意味のないパラメーター名を指定しても、同じ出力が得られます。

$parser->tables_dump({tweedledum => 1, tweedledee => '_'}) ;

名前付きパラメーター スタイルを使用してこの関数を呼び出すことはできますか?

4

7 に答える 7

11

Perl は名前付きパラメーターをネイティブにサポートしていませんが、名前付きパラメーターを (ハッシュまたはハッシュ参照として) 受け入れるように関数を設計することは可能です。関数をどのように実装するかは、関数の作成者次第です。関数が期待する引数を指定する必要があります。そうしないと、予期しない結果が得られます。

于 2012-11-26T02:30:24.037 に答える
9

Perl での名前付きパラメーターの受け渡し (デフォルト値を使用する場合でも) については、オブジェクト指向 Perlの第 6 章で詳しく説明されています。このスタイルは非常に重要であり、オブジェクト コンストラクターで広く使用されています。それが彼らの OO Perl book で説明されている理由です。

それらの例の 2 つを引用します。

# 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";
}

デフォルトを (ハッシュで) 定義する別の方法を示す別の例は次のとおりです。

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";
}
于 2013-08-09T23:46:43.197 に答える
4

Perl.com の Advance Subroutines の記事に従って、パラメーターの意味を明確にするために、パラメーター名と値を含むハッシュを渡そうとしました。

その記事では、名前付きパラメーターのハッシュリファレンスを受け入れるようにサブルーチンを作成する方法について説明しています。それを受け入れるように書かれていないサブルーチンを呼び出している場合、サブルーチンはそれを正しく処理する方法を知りません。

$parser->tables_dump({show_content => 1, col_sep => '_'}) ;

Perl はこれを理解していません。col_sep の値を無視し、デフォルト値で出力します。

過度に衒学的である必要はありませんが、Perl はそれを十分に理解しています。ただし、tables_dumpスカラー パラメータのリストを受け入れるように記述されているだけです。そのように呼び出すと、単一のスカラー パラメータを受け取ります。このパラメーターはたまたまハッシュへの参照ですが、tables_dumpそれを認識していないか気にしないため、参照を の値として使用します$show_content1これはおそらくforを渡すことと同等ですshow_content。なぜなら、1と 可能な参照は両方ともブール値のコンテキストで「true」と評価され$show_content、これはブール値としてのみ使用されると想定しているからです。

2 番目のパラメーターがないため、 には何も割り当てられない$col_sepため、観察したように、デフォルトのセパレーターが使用されます。

于 2012-11-26T15:11:15.147 に答える
4

Perl には、名前付きパラメーターの組み込みサポートはありません。それらを使用したい場合は、そのスタイルで引数を受け入れるように関数を具体的に記述する必要があります。したがって、位置引数で解決する必要があります (または、(おそらくサブクラスで) ラッパー関数を記述します)。

于 2012-11-26T02:21:30.113 に答える
3

それほど複雑ではありません。キーと値のペアをハッシュのように、またはハッシュ参照として渡し、サブルーチンで引数をハッシュまたはハッシュ参照にロードします。

# called like $parser->tables_dump({show_content => 1, col_sep => '_'}) ;
sub TheParser::tables_dump {
    my ($self, $args) = @_;
    if ($args->{show_content} == 1) {
        print join $args->{col_sep}, $self->the_column_data();
        ...
    }
}

別の行で、知っている名前付き引数を適切な名前付き変数にロードできます。

    my ($self, $args) = @_;
    my ($show_content, $col_sep) = @$args{qw(show_content col_sep)};
    if ($show_content == 1) {
       ...
于 2012-11-26T04:41:54.287 に答える
-1

これは私が書いた簡単なプログラムで、名前付きパラメーターのタイプを使用できます。デフォルト値を使用できます。

#!/usr/bin/perl
use strict;
use warnings;
use 5.014;
use POSIX qw/ strftime /;

# Script to get prior Monday (if today is Mon, then Mon a week ago).

for my $day (qw/ Sun Mon Tue Wed Thu Fri Sat /) {
    say "Last $day: ", last_monday( day => $day );  
}

sub last_monday {
    my %arg =  ( time => [localtime],
                 day  => 'mon',
                 span => 1,
                 @_
               );
    my $dow; # day of week

    if    ('sunday'    =~ /$arg{day}/i) { $dow = 0}
    elsif ('monday'    =~ /$arg{day}/i) { $dow = 1}
    elsif ('tuesday'   =~ /$arg{day}/i) { $dow = 2}
    elsif ('wednesday' =~ /$arg{day}/i) { $dow = 3}
    elsif ('thursday'  =~ /$arg{day}/i) { $dow = 4}
    elsif ('friday'    =~ /$arg{day}/i) { $dow = 5}
    elsif ('saturday'  =~ /$arg{day}/i) { $dow = 6}
    else {
        warn "$arg{day} is not a valid day of week. $!";
        return;
    }

    my ($wday, @dmy) = @{ $arg{time} }[6, 3..5];

    # (will work across month, year boundries)
    $dmy[0] -= ($wday - $dow) % 7 || ($arg{span} ? 7 : 0); # $dmy[0] == mday
    return strftime "%Y%m%d", 0,0,0,@dmy;
}
于 2012-11-26T04:47:38.217 に答える