kon*_*pun 5 sorting perl block
我正在尝试在我的一个(面向对象的)包中提供一个排序函数,它接受一个块,并且像标准Perl一样提供$ a和$ b sort.
首先,我在包含包装排序函数的包中尝试做的简化版本:
# In package My::Object
sub sort {
my $self = shift;
my $block = \&{shift @_};
return sort $block @{$self->{arrayRef}}; # I want to use the passed in block with array data contained in this object
}
Run Code Online (Sandbox Code Playgroud)
然后是一个客户端传递块的示例,该块定义了要为排序运行的比较器:
my $obj = My::Object->new([3, 1, 5, 6, 2, 4]); # As an example, these values will be come arrayRef from above
my @sortedVals = $obj->sort({ $a < $b });
Run Code Online (Sandbox Code Playgroud)
有没有办法做我想做的事情,同时还能使用Perl sort?
大多.
要使用bare-block-as-subroutine语法,您需要使用& 原型.通常你应该避免使用原型,但是将子程序作为裸块传递是可接受的少数几次之一.不幸的是,因为它们必须在编译时确定并应用,所以原型不适用于方法.所以你必须使用完整的匿名子程序语法sub { ... }.
my @sortedVals = $obj->sort(sub { $a <=> $b });
Run Code Online (Sandbox Code Playgroud)
$a并且$b是声明sort子例程的包的全局变量(让我们说这是Some::Caller).在类中运行时,sort将设置$My::Object::a,$My::Object::b但子程序将查找$Some::Caller::a和$Some::Caller::b.你可以通过别名他们$a和$b你的$a和你来解决这个问题$b.
sub sort {
my $self = shift;
my $block = shift;
no strict 'refs';
local *{caller.'::a'} = *a;
local *{caller.'::b'} = *b;
return sort $block @{$self->{arrayRef}};
}
Run Code Online (Sandbox Code Playgroud)
local在块的持续时间内生成全局的临时副本,这包括调用的其他子例程,因此这将影响排序.然后,当方法完成时,值将恢复到原来的状态.
Perl全局变量存储在typeglobs中,其中包含具有相同名称的所有全局变量. *a包含$a和@a和%a.通过复制调用者的typeglob,当$My::Object::a更改时,调用者$a也会改变.它们是别名.
该*{...}语法允许您使用另一个变量或表达式在全局变量得到的名字.这称为符号引用.现在我们可以接听来电了*a.使用这种语法通常是一个错误,所以你必须关闭strict其他Perl不会让你这样做.