質問

私は頻繁に利用 shift ド関数パラメータ:

sub my_sub {
    my $self = shift;
    my $params = shift;
    ....
}

しかし、多くの私の同僚宣る shift 実際にう。について教えてください。思う。

sub my_sub {
    my ($self, $params) = @_;
    ....
}

shift?

役に立ちましたか?

解決

引数を解凍するshiftを使用することは悪ではありません。それは一般的な慣例だと(彼らが渡されているどのように多く存在し、どのように依存する)の引数を処理するための最速の方法かもしれません。ここではそれが事実だやや一般的なシナリオの一例です:シンプルなアクセサは、

use Benchmark qw(cmpthese);

sub Foo::x_shift { shift->{'a'} }
sub Foo::x_ref   { $_[0]->{'a'} }
sub Foo::x_copy  { my $s = $_[0]; $s->{'a'} }

our $o = bless {a => 123}, 'Foo';

cmpthese(-2, { x_shift => sub { $o->x_shift },
               x_ref   => sub { $o->x_ref   },
               x_copy  => sub { $o->x_copy  }, });

私のマシン上のPerl 5.8.8での結果ます:

            Rate  x_copy   x_ref x_shift
x_copy  772761/s      --    -12%    -19%
x_ref   877709/s     14%      --     -8%
x_shift 949792/s     23%      8%      --

劇的ではないが、そこにそれがあります。常に確実に見つけるためにターゲットハードウェア上のperlのバージョンにあなたのシナリオをテストします。

shiftあなたがインボカントをオフにシフトし、その後SUPER::メソッドを呼び出し、そのまま残り@_を渡したい場合にも便利です。

sub my_method
{
  my $self = shift;
  ...
  return $self->SUPER::my_method(@_);
}
私は、関数の先頭にmy $foo = shift;操作の非常に長いシリーズを持っていた場合は、

、しかし、私の代わりに@_から大量のコピーを使用して検討するかもしれません。しかし、一般的には、あなたが引数の一握り以上かかる関数やメソッドを持っている場合は、名前付きパラメータを使用して(すなわち、@_ハッシュに%argsのすべてをキャッチ、または単一のハッシュ参照引数を期待して)より良いアプローチです。

他のヒント

それは事の味一種である、悪ではありません。あなたはしばしば一緒に使用されているスタイルが表示されます:

sub new {
    my $class = shift;
    my %self = @_;
    return bless \%self, $class;
}

私は1つの引数があるときshiftを使用する傾向があるか、私は残りの部分とは異なる最初の数の引数を扱いたいときます。

他の人が言ってきたように、

これは、好みの問題です。

私は、一般的にそれは私に、サブルーチンで使用される変数のグループを宣言するための標準的な場所を提供しますので、レキシカルに私のパラメータをシフトすることを好みます。余分な冗長性は、私のコメントをハングアップする素敵な場所を提供します。また、きちんとした形で、デフォルト値を提供することが容易になります。

sub foo {
    my $foo = shift;       # a thing of some sort.
    my $bar = shift;       # a horse of a different color.
    my $baz = shift || 23; # a pale horse.

    # blah
}
あなたがすべてであなたの引数を開梱しないでください、あなたのルーチンを呼び出すの速度について本当に心配している場合は、

- 直接@_を使用してそれらにアクセスします。注意してください、それらは、作業している呼び出し側のデータへの参照です。これは、POEで一般的なイディオムです。 POEは、名前で位置パラメータを取得するために使用する定数の束を提供しています:

sub some_poe_state_handler {
    $_[HEAP]{some_data} = 'chicken';
    $_[KERNEL]->yield('next_state');
}

今、あなたは習慣的にシフトしてのparamsを解凍した場合、あなたが得ることができる大きな愚かなバグがこれ一つであります:

sub foo {
    my $foo = shift;
    my $bar = shift;
    my @baz = shift;

    # I should really stop coding and go to bed.  I am making dumb errors.

}

私は、一貫性のあるコードスタイルは、任意の特定のスタイルよりも重要だと思います。すべての私の同僚は、リストの割り当てスタイルを使用した場合、私もそれを使用すると思います。

私の同僚は、解凍するシフトを使用して大きな問題があったと述べている場合、

、私はそれが悪い理由のデモンストレーションをお願いしたいです。ケースが固体である場合は、私が何かを学ぶと思います。ケースが偽であれば、私はそれに反論し、抗知識の普及を止めるに役立つ可能性があります。それから私は、我々は標準的な方法を決定することを示唆していると、将来のコードのためにそれに従うだろう。私も規格に決めたかどうかを確認するためのPerl ::評論家ポリシーを設定しようとする可能性があります。

格@_リストであhelpulョンが特徴です。

でも、少しやすくな追加-名前のパラメータは後日、内容を変更コードを一人で考えこの特徴で、同様のどのように仕上げのリストまたはハッシュとの末尾に','で少しや追加のです。

ばの習慣を熟、移動、引数という見方もあるかもしれないが有害で編集する場合のコードを追加するには追加の引数が、微妙なバグの場合の支払いがない。

例えば

sub do_something {
 my ($foo) = @_;
}

後編集

sub do_something {
  my ($foo,$bar) = @_; # still works
}

しかし

sub do_another_thing {
  my $foo = shift;
}

この場合は、同僚の方は最初の形dogmatically(かいシフトが悪)編集ファイルや欠席をひたすらの更新ここを読む

sub do_another_thing {
  my ($foo, $bar)  = shift; # still 'works', but $bar not defined
}

その場合について紹介して微妙なくなる場合もあります

配@_きよりコンパクトで効率的な垂直スペースが少人数のパラメータを割り当てます。ことができますただしデフォルトの引数を使用している場合、ハッシュスタイルの名前の関数パラメータ

例えば

 my (%arguments) = (user=>'defaultuser',password=>'password',@_);

ういうスタイル/味わいです。私の最も重要なことは"というスタイルまたはその他との整合性の原則を守の原則の少なくとも驚きです。

私はshiftが悪だとは思いません。 shiftの使用は、実際の変数の名前にあなたの意欲を示して - 。$_[0]を使用しての代わりに

機能への唯一つのパラメータがあるとき、

個人的に、私はshiftを使用しています。私は複数のパラメータを持っている場合、私はリストコンテキストを使用します。

 my $result = decode($theString);

 sub decode {
   my $string = shift;

   ...
 }

 my $otherResult = encode($otherString, $format);

 sub encode {
   my ($string,$format) = @_;
   ...
 }

はPerl ::評論家は、ここではあなたの友達です。これは、ダミアン・コンウェイ氏の著書Perlのベストプラクティスに設定し、「標準」に続きます。 --verbose 11とそれを実行すると、あなたに物事が悪い理由について説明します。あなたの潜水艦で最初@_開梱しないと、(5点満点)重大度4です。例えばます:

echo 'package foo; use warnings; use strict; sub quux { my foo= shift; my (bar,baz) = @_;};1;' | perlcritic -4 --verbose 11

Always unpack @_ first at line 1, near 'sub quux { my foo= shift; my (bar,baz) = @_;}'.
  Subroutines::RequireArgUnpacking (Severity: 4)
    Subroutines that use `@_' directly instead of unpacking the arguments to
    local variables first have two major problems. First, they are very hard
    to read. If you're going to refer to your variables by number instead of
    by name, you may as well be writing assembler code! Second, `@_'
    contains aliases to the original variables! If you modify the contents
    of a `@_' entry, then you are modifying the variable outside of your
    subroutine. For example:

       sub print_local_var_plus_one {
           my ($var) = @_;
           print ++$var;
       }
       sub print_var_plus_one {
           print ++$_[0];
       }

       my $x = 2;
       print_local_var_plus_one($x); # prints "3", $x is still 2
       print_var_plus_one($x);       # prints "3", $x is now 3 !
       print $x;                     # prints "3"

    This is spooky action-at-a-distance and is very hard to debug if it's
    not intentional and well-documented (like `chop' or `chomp').

    An exception is made for the usual delegation idiom
    `$object->SUPER::something( @_ )'. Only `SUPER::' and `NEXT::' are
    recognized (though this is configurable) and the argument list for the
    delegate must consist only of `( @_ )'.

リスト割り当ての最適化があります。

私は見つけることができる唯一の参照は、この1 のです。

  うっかり引き起こした最適化を、無効

5.10.0   リストで測定可能なパフォーマンスの低下   そのようなことが多いために使用されるように割り当て、   @_から関数のパラメータを割り当てます。   最適化は、再instatedされました、   そして、パフォーマンスの低下は、固定されます。

これは、影響を受けたパフォーマンスの低下の一例である。

sub example{
  my($arg1,$arg2,$arg3) = @_;
}

これはない本質的に悪であるが、一つ一つが比較的遅いサブルーチンの引数をオフに引っ張ってそれを使用して、コードの行のより多くを必要とする。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top