52

&Perl サブルーチンの呼び出しに使用すべきではない、と聞いたことがあります。

function($a,$b,...);
# opposed to
&function($a,$b,...);

引数リストがオプションになることは知っていますが、 を使用するのが適切な&場合と、絶対に使用してはならない場合は何ですか?

また、ここで ? を省略すると、パフォーマンスがどのように向上し&ますか?

4

4 に答える 4

55

私は頻繁に を乱用し&ていますが、ほとんどの場合、奇妙なインターフェース操作を行っているためです。これらの状況のいずれも必要ない場合は、&. これらのほとんどは、サブルーチンを呼び出すのではなく、サブルーチン定義にアクセスするためのものです。それはすべてperlsubにあります。

  1. 名前付きサブルーチンへの参照を取得します。これはおそらくほとんどの Perler にとって唯一の一般的な状況です:

     my $sub = \&foo;
    
  2. 同様に、型グロブに割り当てると、別の名前でサブルーチンを呼び出すことができます。

     *bar = \&foo;
    
  3. テスト スイートのように、サブルーチンが定義されていることを確認します。

     if( defined &foo ) { ... }
    
  4. 一般的であってはならないサブルーチン定義の削除:

     undef &foo;
    
  5. 呼び出す適切なサブルーチンを選択するだけのディスパッチャ サブルーチンを提供します。&これは、私がサブルーチンを呼び出すために使用する唯一の状況であり、ディスパッチャーを何度も呼び出すことが予想され、操作から少しパフォーマンスを絞り出す必要がある場合:

     sub figure_it_out_for_me {
        # all of these re-use the current @_
          if( ...some condition... ) { &foo     } 
       elsif( ...some other...     ) { &bar     }
       else                          { &default }
       }
    
  6. 現在の引数スタックを使用して別のサブルーチンにジャンプする (およびコール スタック内の現在のサブルーチンを置き換える) ことは、特にディスパッチではまれな操作ですAUTOLOAD

     goto ⊂
    
  7. Perl ビルトインにちなんで名付けたサブルーチンを呼び出します。は&常にユーザー定義のものを提供します。そのため、 Learning Perlでそれを教えています。通常はあまりやりたくありませんが、 の機能の 1 つです&

それらを使用できる場所がいくつかありますが、より良い方法があります。

  1. Perl ビルトインと同じ名前のサブルーチンを呼び出す。Perl ビルトインと同じ名前のサブルーチンを持たないでください。perlfuncをチェックして、使用してはならない組み込みの名前のリストを確認してください。

  2. プロトタイプを無効にします。それが何を意味するのか、またはなぜそれが必要なのかわからない場合は、. を使用しないでください&。一部のブラック マジック コードはそれを必要とする場合がありますが、そのような場合は、自分が何をしているのかを知っている可能性があります。

  3. サブルーチン参照を逆参照して実行する。->表記をそのまま使う。

于 2009-08-28T19:37:44.427 に答える
38

IMO、使用する理由があるの&は、次のようなコードリファレンスを取得または呼び出す場合だけです。

sub foo() {
    print "hi\n";
}

my $x = \&foo;
&$x();

ほとんどの状況で絶対に使用してはならない主な使用時間は、デフォルト以外の呼び出し動作を指定するプロトタイプを持つサブルーチンを呼び出すときです。これが意味することは、一部のプロトタイプでは、引数リストの再解釈が可能であるということです。たとえば、仕様を参照に変換するなどです。したがって、潜水艦はそれらの再解釈が発生したことを期待しており、手動でそれらを模倣するために必要な長さまで行かない限り、潜水艦は予想とは大きく異なる入力を取得します.@array%hash

主に人々は、あなたがまだ Perl 4 スタイルで書いていることを伝えようとしていると思います。現在、Perl 5 と呼ばれる、よりクリーンで優れたものがあります。

パフォーマンスに関しては、Perl がサブコールを最適化するさまざまな方法がありますが&、主なものの 1 つは定数のインライン化です。

&を使用するとパフォーマンスが向上する状況も 1 つありますfoo(@_)。を使用する&fooと、 よりもはるかに高速ですfoo(@_)。プロファイリングによって、そのマイクロ最適化が必要であることが明確にわかっていない限り、お勧めしません。

于 2009-08-28T14:35:32.100 に答える
18

&subroutine()フォームは、プロトタイプのチェックを無効にします。これはあなたが望むものかもしれないし、そうでないかもしれません。

http://www.perl.com/doc/manual/html/pod/perlsub.html#Prototypes

プロトタイプを使用すると、サブルーチン引数の数とタイプを指定し、コンパイル時にそれらをチェックすることができます。これは、有用な診断支援を提供できます。

プロトタイプは、メソッド呼び出し、または&プレフィックスを使用して昔ながらのスタイルで行われた呼び出しには適用されません。

&は、サブルーチンまたはコード参照を参照または逆参照するために必要です

例えば

sub foo {
   # a subroutine
}

my $subref = \&foo; # take a reference to the subroutine

&$subref(@args);  # make a subroutine call using the reference.

my $anon_func = sub { ... }; # anonymous code reference
&$anon_func(); # called like this

プロトタイプは、サブルーチン参照にも適用できません。

&subroutineフォームは、いわゆるマジック後藤フォームでも使用されます。

この式goto &subroutineは、@ _の現在の値を使用して、現在の呼び出しコンテキストを名前付きサブルーチンへの呼び出しに置き換えます。

基本的に、名前の付いたサブルーチンへの呼び出しを使用して、1つのサブルーチンへの呼び出しを完全に切り替えることができます。これは、AUTOLOADブロックでよく見られます。ここでは、おそらく@_を変更して、遅延サブルーチン呼び出しを行うことができますが、プログラムは、指定されたsubへの呼び出しであるかのように完全に見えます。

例えば

sub AUTOLOAD {
    ...
    push @_, @extra_args; # add more arguments onto the parameter list
    goto &subroutine ; # change call another subroutine, as if we were never here
}

}

潜在的に、これは末尾呼び出しの除去に役立つ可能性があります。

このテクニックの詳細な説明はこちらをご覧ください

于 2009-08-28T14:39:42.017 に答える
1

「&」の使用に反対する意見を読んだことがありますが、ほぼ常に使用しています。そうしないと時間を節約できます。私は、コードのどの部分が特定の関数を呼び出しているかを探すために、Perl のコーディング時間のかなりの部分を費やしています。先頭に & を付けると、すぐに検索して見つけることができます。先頭に & を付けないと、関数定義、コメント、およびデバッグ ステートメントが表示され、探しているものを見つけるために調べなければならないコードの量が通常 3 倍になります。

「&」を使用しない主な利点は、関数プロトタイプを使用できることです。しかし、Perl 関数プロトタイプは、エラーを防ぐのと同じくらい頻繁にエラーを作成する可能性があります。これは、引数リストを取得して、予期しない方法で再解釈するため、関数呼び出しが文字どおりに引数を渡さなくなるためです。

于 2015-03-11T03:35:10.020 に答える