So I have a Perl class. It has a sort()
method, and I want it to be more or less identical to the built-in sort()
function:
$object->sort(sub ($$) { $_[0] <=> $_[1] });
But I can't do:
$object->sort(sub { $a <=> $b });
Because of scoping. But the List::Util module does this with reduce()
. I looked at the List::Util module, and they do some rather nasty things with no strict 'vars'
to make this happen. I tried that, but to no avail.
It is my understanding that reduce()
works the way it does because it is exported into the appropriate namespace, and thus my class can't do this since the function is quite firmly in another namespace. Is this correct, or is there some (undoubtedly more hideous and ill-advised) way to do this in my situation?
Strictly speaking, the default scoping of variables in Perl is the package global.
There is a strange scalar variable called $_ in Perl, which is the default variable, or in other words the topic. In Perl, several functions and operators use this variable as a default, in case no parameter is explicitly used.
$$ The process number of the perl running this script. (Mnemonic: same as shells.) $? The status returned by the last pipe close, backtick (\`\`) command or system operator.
Perl has three main variable types: scalars, arrays, and hashes.
Well, the other two answers are both half-right. Here's a working solution that actually sorts:
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
Presumably you'd sort some data that's actually part of the object.
You need the caller
magic so you're localizing $a
and $b
in the caller's package, which is where Perl is going to look for them. It's creating global variables that only exist while that sub is being called.
Note that you will get a 'name used only once' with warnings
; I'm sure there's some hoops you can jump through to avoid this, somehow.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With