Perl变量范围问题

Chr*_*utz 7 perl scope class

所以我有一个Perl课程.它有一个sort()方法,我希望它与内置sort()函数或多或少相同:

$object->sort(sub ($$) { $_[0] <=> $_[1] });
Run Code Online (Sandbox Code Playgroud)

但我做不到:

$object->sort(sub { $a <=> $b });
Run Code Online (Sandbox Code Playgroud)

因为范围.但是List :: Util模块可以实现这一点reduce().我查看了List :: Util模块,他们做了一些相当讨厌的事情no strict 'vars'来实现这一点.我试过了,但无济于事.

我的理解是reduce()按照它的方式工作,因为它被导出到适当的命名空间,因此我的类不能这样做,因为该函数在另一个命名空间中非常牢固.这是正确的,还是有一些(无疑是更可怕和不明智的)方式在我的情况下这样做?

Eev*_*vee 9

那么,另外两个答案都是半对的.这是一个实际排序的工作解决方案:

package Foo;

use strict;
use warnings;

sub sort {
    my ($self, $sub) = @_;

    my ($pkg) = caller;
    my @x = qw(1 6 39 2 5);
    print "@x\n";
    {
        no strict 'refs';
        @x = sort {
            local (${$pkg.'::a'}, ${$pkg.'::b'}) = ($a, $b);
            $sub->();
        } @x;
    }
    print "@x\n";

    return;
}


package main;

use strict;
use warnings;

my $foo = {};
bless $foo, 'Foo';

$foo->sort(sub { $a <=> $b });
# 1 6 39 2 5
# 1 2 5 6 39
Run Code Online (Sandbox Code Playgroud)

据推测,你可以对一些实际上属于对象的数据进行排序.

你需要caller魔法,所以你要本地化,$a$b在调用者的包中,这是Perl将要寻找它们的地方.它正在创建仅在调用该子时存在的全局变量.

请注意,您将获得"仅使用一次"的名称warnings; 不管怎样,我确信你可以通过一些箍来避免这种情况.

  • 这可能对你的目的来说足够好,但它很脆弱.无法保证比较函数属于与`sort`方法的调用者相同的包.这就是Sub :: Identify的用武之地. (2认同)