48

私は最近 Perl について読んでいて、Perl がサブルーチンに渡された引数をどのように処理するかについて少し困惑しています。

Python、Java、PHP などの言語では、関数定義は (疑似コードで) 次の形式を取ります。

function myFunc(arg1, arg2) {
    // Do something with arg1 and arg2 here
}

それでも、Perl では次のようになります。

sub mySub {
    # @_ holds all arguments passed
}

そして、私が理解しているように、それが唯一の方法です。

  • 呼び出し元が 2 つの引数のみを渡すように制限したい場合はどうすればよいでしょうか?

  • これは、Perl が他の言語 (つまり、Python、C など) で可変数引数以外を許可していないだけでしょうか?

  • いつか問題になるんじゃないの?

  • 他の言語のすべてのデフォルトの引数番号チェックはどうですか? Perl で明示的にそれを行う必要がありますか? 例えば

      sub a_sub {
          if (@_ == 2) {
              # Continue function
          }
          else {
              return false
          }
      }
    
4

7 に答える 7

82

Perl 環境は、以前に遭遇した言語とはかなり異なるため、警戒しています。

強力な型付けと関数プロトタイプを信じる人々はここで意見を異にするでしょうが、そのような制限が役立つことはめったにないと思います。Cは、関数に間違った数のパラメーターを頻繁に渡して有用であることに気付いたことがありますか?

@_最近の Perl では、 の内容を字句スカラー変数のリストにコピーするのが最も一般的です。

sub mysub {
  my ($p1, $p2) = @_;
  ... etc.
}

そうすれば、渡されたすべてのパラメーターは@_($_[0]など$_[1]) の要素として使用できるようになりますが、期待されるものは名前が付けられて and に表示され$p1ます$p2(ただし、これらの名前は適切に選択する必要があることを理解していただければ幸いです)。

サブルーチンがメソッドである特定のケースでは、最初のパラメーターは特別です。他の言語ではselfまたはthisですが、Perl では単純に の最初のパラメーターで@_あり、好きなように呼ぶことができます。そのような状況では、あなたは見るでしょう

sub method {
  my $self = shift;
  my ($p1, $p2) = @_;
  ... etc.
}

コンテキストオブジェクト(またはクラスメソッドの場合はクラスの名前)が$self(慣例で想定される名前)に抽出され、残りのパラメーターは@_直接アクセスされるか、より通常はローカルにコピーされるように残りますなど$p1のスカラー変数$p2

ほとんどの場合、型チェックも行われないため、任意のスカラーをサブルーチン パラメーターとして渡すことができます。use strictとがコンテキスト内にある限りuse warnings、サブルーチンが 1 つの形式のスカラーに対して実行できる操作は、通常、別の形式では正しくないという単純な理由から、これでさえデバッグするのは一般に簡単です。

元々はオブジェクト指向の Perl に関してはカプセル化に関するものでしたが、Larry Wall からのこの引用は非常に関連性があります。

Perl は強制されたプライバシーに夢中になりません。散弾銃を持っているからではなく、招待されていないので、リビングルームから離れた方がいいでしょう。

C は、実行時ではなくコンパイル時に障害のあるプログラムを失敗させることができれば、効率が大幅に向上する時代に設計および実装されました。現在は状況が変わっていますが、クライアント側の JavaScript で同様の状況が発生しており、インターネットからデータを取得する前にコードが間違っていることを知っておくと便利です悲しいことに、JavaScript パラメーターのチェックは本来より緩くなっています。


アップデート

教育目的での Perl の有用性を疑う人のために、私は、Perl のメカニズムが非常に単純で直接的であるため、そのような目的に理想であることを提案します。

  • Perl サブルーチンを呼び出すと、呼び出し内のすべてのパラメーターが.ini ファイルにエイリアスさ@_ます。それらを直接使用して実際のパラメーターに影響を与えるか、コピーして外部アクションを防ぐことができます

  • Perl サブルーチンをメソッドとして呼び出すと、呼び出し元のオブジェクトまたはクラスが最初のパラメーターとして提供されます。繰り返しますが、サブルーチン (メソッド) は好きなことを行うことができます@_

于 2013-10-07T21:05:55.950 に答える
8

何らかの理由で、Perl はリストが好きで、静的型付けが嫌いです。サブルーチンの引数はではなく参照によって@_渡されるため、配列は実際には多くの柔軟性をもたらします。たとえば、これにより、out-arguments を実行できます。

my $x = 40;
add_to($x, 2);
print "$x\n"; # 42

sub add_to { $_[0] += $_[1] }

…しかし、これは歴史的なパフォーマンス ハックです。通常、引数はリスト代入によって「宣言」されます。

sub some_sub {
  my ($foo, $bar) = @_;
  #               ^-- this assignment performs a copy
  ...
}

これにより、通常はより望ましい値渡しサブルーチンのセマンティクスが作成されます。はい、未使用の引数は単純に忘れられます。引数が少なすぎても自動エラーは発生しません。変数には が含まれているだけundefです。のサイズをチェックするなど、任意の検証を追加できます@_


将来、名前付きパラメーターを最終的に利用可能にする計画があり、次のようになります。

sub some_sub($foo, $bar) { ... }

モジュールをインストールすると、今日この構文を使用できます。しかし、さらに優れたものがあります。次のような構文を使用signaturesできる を強くお勧めします。Function::Parameters

fun some_sub($foo, $bar = "default value") { ... }

method some_method($foo, $bar, :$named_parameter, :$named_with_default = 42) {
  # $self is autodeclared in methods
}

これは、実験的な型チェックもサポートしています。

パーサー拡張 FTW!

于 2013-10-07T22:05:36.267 に答える
6

Perl でより厳密なパラメータ チェックを本当に課したい場合は、Params::Validateのようなものを見ることができます。

于 2013-10-08T13:58:31.463 に答える
5

Perl には、見慣れたパラメーター プレースホルダーのプロトタイピング機能がありますが、多くの場合不要です。

sub foo($){
    say shift;
}; 
foo();      # Error: Not enough arguments for main::foo
foo('bar'); # executes correctly

もしそうならsub foo($$){...}、2つのオプションではない引数が必要になります(例foo('bar','baz')

于 2013-10-07T20:56:49.750 に答える
3

あなたはただ使うことができます:

my ($arg1, $arg2) = @_;

使用できる引数の数を明示的に制限するには:

my $number =2;
die "Too many arguments" if @_ > $number;
于 2013-10-07T20:38:09.863 に答える
2

最近 Perl について読んでいる場合は、最近の Perl について読んでください。Modern Perlの本も無料で読むことができます。

関数シグネチャに関するその本からのいくつかの例を次に示します。

sub greet_one($name = 'Bruce') {
    say "Hello, $name!";
}
sub greet_all($leader, @everyone) {
    say "Hello, $leader!";
    say "Hi also, $_." for @everyone;
}

sub make_nested_hash($name, %pairs) {
    return { $name => \%pairs };
}
于 2018-01-20T18:26:11.040 に答える