8

次のようなスクリプトとパッケージがあります。

# file: sortscript.pl
use strict;
use warnings;
use SortPackage;

my @arrays = ([1,"array1"],[10,"array3"],[4,"array2"]);

print "Using sort outside package\n";
foreach (sort SortPackage::simplesort @arrays){
    print $_->[1],"\n";
}

print "\nUsing sort in same package\n";
SortPackage::sort_from_same_package(@arrays);

--

# file: SortPackage.pm
use strict;
use warnings;
package SortPackage;

sub simplesort{
    return ($a->[0] <=> $b->[0]);
}

sub sort_from_same_package{
    my @arrs = @_;
    foreach (sort simplesort @arrs){
        print $_->[1],"\n";
    } 
}
1;

スクリプトを実行すると、次の出力が生成されます。

$ perl sortscript.pl
Using sort outside package
Use of uninitialized value in numeric comparison (<=>) at SortPackage.pm line 15.
Use of uninitialized value in numeric comparison (<=>) at SortPackage.pm line 15.
Use of uninitialized value in numeric comparison (<=>) at SortPackage.pm line 15.
Use of uninitialized value in numeric comparison (<=>) at SortPackage.pm line 15.
Use of uninitialized value in numeric comparison (<=>) at SortPackage.pm line 15.
Use of uninitialized value in numeric comparison (<=>) at SortPackage.pm line 15.
array1
array3
array2

Using sort in same package
array1
array2
array3

サブルーチンが別のパッケージにあると、サブルーチンを正しく使用してソートできないのはなぜですか?

4

3 に答える 3

6

前述のように、$a$bはパッケージ グローバルであるため、別の解決策は、一時的に呼び出しサイトのグローバルを package 内のグローバルにエイリアスすることですSortPackage

{
    local (*a, *b) = (*SortPackage::a, *SortPackage::b);
    foreach (sort SortPackage::simplesort @arrays){
        print $_->[1],"\n";
    }
}

しかし、もちろん、これはかなり醜いです。SortPackageコンパレータだけでなく、完全な並べ替えルーチンをエクスポートするだけです。

package SortPackage;
use strict;

sub _sort_by_first_element_comparator {
    return $a->[0] <=> $b->[0];
}

sub sort_by_first_element {
    return sort _sort_by_first_element_comparator @_;
}
于 2012-07-16T17:47:20.197 に答える
6

$aおよび$bは、特別な「パッケージ グローバル」変数です。

メイン スコープ$a$bコンパレータ関数を使用するには、 $::aor $main::a(および同様に for $b) を参照する必要があります。

ただし、そのコンパレーター関数は、他のパッケージから呼び出された場合、または独自のパッケージ内から呼び出された場合でも機能しません。

関数については、perlvarsヘルプとを参照してください。解決策は、後者のヘルプ テキストにもあります。perldocsort

サブルーチンのプロトタイプが の場合、通常のサブルーチンと同様に、"($$)"比較される要素は で参照渡しされます。@_これは、比較対象の要素がパッケージのグローバル変数としてサブルーチンに渡されるプロトタイプ化されていないサブルーチンよりも遅くなります$a(以下の$b例を参照)。後者の場合、$aand$bをレキシカルとして宣言するのは通常非生産的であることに注意してください。

于 2012-07-16T16:22:42.080 に答える
5

特殊変数$a$bはパッケージ グローバルです。あなたのサブルーチンは と を期待$SortPackage::aして$SortPackage::bいます。から呼び出すとsortscript.pl、変数$main::a$main::bが によって設定されsortます。

解決策は、プロトタイプのサブルーチンを使用することです。

package SortPackage;

sub simplesort ($$) {
    return ($_[0]->[0] <=> $_[1]->[0]);
}

少し遅くなりますが(事前設定されたグローバルを読み取る代わりに実際のパラメーターが渡されるため)、試みているように、他のパッケージのサブルーチンを名前で使用できます。

于 2012-07-16T16:26:29.193 に答える