web-dev-qa-db-ja.com

Perl関数で複数の引数を取得するにはどうすればよいですか?

私のコードでは、次のように、関数呼び出しからパラメーターを抽出するかなり原始的な方法を使用しています。

sub addSix ($$$$$$) {
    my ($a, $b, $c, $d, $e, $f) = (shift, shift, shift, shift, shift, shift);
    return $a + $b + $c + $d + $e + $f;
}

print addSix (1, 2, 3, 4, 5, 6) . "\n";

(プリミティブコードを忘れてください。顕著なビットは複数のshift呼び出しです)。

今ではそれは私にはかなり厄介に思えますが、Perlには次のようなものがあるかもしれません:

my ($a, $b, $c, $d, $e, $f) = shift (6);

または同様のもの。

しかし、私はそのようなものを見つけることができません。これに配列を使用できることはわかっていますが、それでも配列を個々のスカラーに解凍する必要があると思います。これは、6つのパラメーターが類似している上記の例の場合にはそれほど悪くはありませんが、配列として実際には適していない場合に興味があります。

shiftキーワードの泥沼に終わることなく、どのようにしてパラメーターを抽出できますか?

14
paxdiablo

次のように入力するだけです。

my ($a, $b, $c, $d, $e, $f) = (@_);

そのプロトタイプがなく、そのサブが6つを超える引数で呼び出された場合、6番目以降の引数は単に「一致しません」$fは6番目の引数に設定されます。

6番目以降のすべての引数をキャッチしたい場合は、次のように実行できます。

my ($a, $b, $c, $d, $e, $f, @others) = (@_);

スカラーのリストが右側のリストよりも長い場合、最後の要素はundefになります。

32
Mat

実際の必要がない限り、プロトタイプの使用は強くお勧めしません。

Perlの場合と同様に、それを行う方法は複数あります。

渡された最初の6つのパラメーターのみを追加することを保証する1つの方法は次のとおりです。

use List::Util 'sum';

sub addSix { sum @_[0..5] }

または、自己文書化コードが好きな場合:

sub addSix {

    my @firstSix = @_[0..5];  # Copy first six elements of @_
    return sum @firstSix;
}
7
Zaid

これは古いスレッドだと思いますが、複数の値をシフトするためのより良い方法を考えさせられました。これはすべてちょっとした楽しみです...主に教育目的でこれを投稿します。

確かに、_($x, $y) = @__を保持したい場合は_@__が最適ですが、何らかの理由で引数をシフトしたい場合はどうでしょうか。おそらく、_@__の残りの引数の数によって決定される追加のサブルーチン機能が必要です。

これを行うために私が考えることができる最もクリーンな1行の方法は、単純なマップを使用することです

_sub shiftySub {
    map { $_ = shift } my ($v, $w, $x, $y);
    # @_ now has up to 4 items removed
    if (@_) { ... } # do stuff if arguments remain
}
_
  • 4つの引数が指定されている場合、_@__はサブスコープで空になります。
  • 5つの引数が指定されている場合、_@__のサブスコープには1つの項目が残っています。
  • 3つの引数が指定されている場合、サブスコープでは_@__は空であり、_$y_はundefです。

paxdiablo の理論上のshift(6)演算子に関しては、この操作を実行する独自の関数を作成できます。

_sub shifter (\@;$) {
    my ( $array, $n ) = ( @_, 1 );
    splice( @$array, 0, $n );
}
_

この関数は、参照渡しのプロトタイプ(プロトタイプを使用する必要がある非常に限られた理由の1つ)を適用して、呼び出し元のスコープ内で配列がシフトされるようにすることで機能します。次に、このように単純に使用します...

_my @items = ('one', 'two', 'three', 'four');
my ($x, $y) = shifter(@items, 2);
# or as a replacement for shift
my $z = shifter(@items)
# @items has 1 item remaining in this scope!
_

もちろん、このshifter関数を他のサブ内で使用することもできます。このような関数の主な欠点は、演算子の両側で割り当ての数を追跡する必要があることです。

_my $post = 'informative' || 'interesting';_を願っています

3
Joshua