web-dev-qa-db-ja.com

オプションのパラメーターをPerl関数に渡す方法は?

関数にいくつかのパラメーターを渡したい(そのうちの1つはオプション)。私が知っている唯一の方法は、パラメーターとしてリスト(@)を使用することです。したがって、何も含まれていないか、1つの要素が含まれているため(undefにはなりません)、次のコードを使用できます。

sub someFunction($$@) {
    my ( $oblig_param1, $oblig_param2, $option_param ) = @_;
    ...
} 

このコードは機能しますが、最善の回避策ではないかもしれません。
それを行う他の方法はありますか?
ありがとうございました。

18
evgeny9

プロトタイプでセミコロンを使用して、必須パラメーターの終わりを示すことができます。

sub someFunction($$;$) {
  my ( $oblig_param1, $oblig_param2, $option_param ) = @_;
  ...
}

;@または%の前ではオプションです。これは the docs に従って、「他のすべてのものを取り除きます」。

編集:DVKがコメントで指摘している(そしてTLPがここで別の答えを強調している)ので、プロトタイプを単に回避することをお勧めします。

sub someFunction {
  my ( $oblig_param1, $oblig_param2, $option_param ) = @_;
  ...
}

Perlプロトタイプには用途があります(ほとんどの場合、Perlの組み込み関数が行うように、暗黙のコンテキスト強制を引数に提供します)。それらは、関数が正しい数とタイプの引数で呼び出されていることを確認するメカニズムとしてしないでください

18
Ted Hopp

Prototypes (サブ宣言の($$@)部分)自体はオプションです。それらは非常に特定の用途があり、それが何であるかがわからない場合は、使用しない方が良いでしょう。 perlsubから:

...この機能の目的は主に、組み込み関数のように機能するサブルーチンを定義できるようにすることです

サブ宣言からプロトタイプを削除するだけで、任意の引数を使用できます。

sub someFunction {
    my ( $oblig_param1, $oblig_param2, $option_param ) = @_;
    if (defined $option_param) {
        # do optional things
    }
    $option_param //= "default optional value";
    ....
} 
37
TLP

パラメータを_$parameter_ハッシュ参照にグループ化することをお勧めします。これは、いくつかのオプション(必須またはオプション)を提供する必要がある場合に特に便利です。

パラメータにアクセスするには、単に_$parameter->{oblig1}_または_$$parameter{option2}_を使用します。

ハッシュリファレンスを渡すと、開発時に特に便利になります。そのため、_$oblig3_が必要になったときに、引数の順序は、呼び出し元でもサブルーチン自体でも変わりません。前と後を比較してください:


_# BEFORE $oblig3

--------------------------+-------------------------
# Caller                  | # Sub
--------------------------+-------------------------
someFunc( $oblig1,        | sub {
          $oblig2,        |   my ( $oblig1,
          $option1 );     |        $oblig2,
                          |        $option1 ) = @_;
                          | }
--------------------------+-------------------------

# AFTER $oblig3

--------------------------+-------------------------
# Caller                  | # Sub
--------------------------+-------------------------
someFunc( $oblig1,        | sub {
          $oblig2,        |   my ( $oblig1,
          $oblig3,        |        $oblig2,
          $option1 );     |        $oblig3,
                          |        $option1 ) = @_;
                          | }
--------------------------+-------------------------
_

引数の順序は呼び出し元とサブルーチンの両方で変化するため、順序を維持して尊重する必要があります。

Hashrefsを使用すると、引数の順序を気にする必要はありません。

_--------------------------+-------------------------
# Caller                  | # Sub
--------------------------+-------------------------
someFunc({ oblig1  => 1   | sub {
           oblig2  => 2   |   my ( $params ) = @_;
           option1 => 1   |   # No changes to    
           oblig3  => 7   |   # argument passing
         });              |  }    
                          | 
--------------------------+-------------------------
_

サブルーチンの設計ニーズに応じて、次のサブルーチン引数パターンを利用できます。

  1. my ( $mandatory_parameters, $optional_parameters ) = @_;

    このパターンは、それぞれが複数ある場合に役立ちます。このアプローチの優れた点は、_$optional_parameters_が渡されない場合は未定義であるため、デフォルトのケースを実行できる_if ! $optional_parameters;_です。

    必須パラメータは後で確認する必要があることに注意してください:

    _for ( qw/ a b c / ) { 
        die "Missing '$_' parameter\n"
          unless exists $mandatory_parameters->{$_};
    }
    _
  2. my ( $parameters ) = @_;

    必須パラメーターがほとんどないか、まったくない場合に役立ちます。

    また、デフォルトの動作を変更するためにパラメーターを渡す場合にも非常に効果的です。パッケージのスコープで_$default_parameters_を定義することにより、パラメーターが明示的に渡されない限り、後続のワンライナーでデフォルトをロードできます。

    _$parameters = { %$default_parameters, %$parameters };_

14
Zaid