10

匿名のバイナリ関数で変数を使用$aしたいのですが、コードが次のようになっている理由がわかりません。$bsort {$a <=> $b} (1, 2, 3)

#!/usr/bin/env perl
use strict;
use warnings;

Foo::Bar(sub { $a + $b });

package Foo;
sub Bar {
    my ($function) = @_; 

    for my $i (1, 2, 3) {
        local ($a, $b) = ($i, $i);
        print $function->() . "\n";
    }
}    

動作しません。その間

#!/usr/bin/env perl
use strict;
use warnings;

Foo::Bar(sub { $_ });

package Foo;
sub Bar {
    my ($function) = @_; 

    for my $i (1, 2, 3) {
        local $_ = $i;
        print $function->() . "\n";
    }
}

正常に動作します。

私は何が間違っているのですか?

4

2 に答える 2

14

$aおよび$bは特別なパッケージ変数です。Foo::Barパッケージ内から呼び出しているので、設定して機能mainさせる必要があります。を使用して、呼び出し元のパッケージの名前を取得できます。これは機能するはずです:$main::a$main::bcaller

#!/usr/bin/env perl
use strict;
use warnings;

Foo::Bar(sub { $a + $b });

package Foo;
sub Bar {
    my ($function) = @_; 
    my $pkg = caller;

    for my $i (1, 2, 3) {
        no strict 'refs';
        local *{ $pkg . '::a' } = \$i;
        local *{ $pkg . '::b' } = \$i;
        print $function->() . "\n";
    }
}    
于 2012-01-02T18:42:03.983 に答える
0

誰かが興味を持っている場合に備えて、List :: MoreUtils :: PP v.0.428からのコピーアンドペースト(2017年12月現在):

# begin copyrighted content
sub reduce_u(&@)
{
    my $code = shift;

    # Localise $a, $b
    my ($caller_a, $caller_b) = do
    {
        my $pkg = caller();
        no strict 'refs';
        \*{$pkg . '::a'}, \*{$pkg . '::b'};
    };

    local (*$caller_a, *$caller_b);
    *$caller_a = \();
    for (0 .. $#_)
    {
        *$caller_b = \$_[$_];
        *$caller_a = \($code->());
    }

    ${*$caller_a};
}
# end copyrighted content

上記のサンプルとは、の影響を受ける領域のみが異なりno strict 'refs';ます。おそらく、厳密なことなしにはできないでしょう。

于 2017-12-25T09:22:23.480 に答える