Turning our attention to sort, I have had need recently for externalising the compare function. Consider this:
I have a new object of class Foo, which has an iterator. In my design of Foo.pm, I want the user to be able to choose to sort or not to sort via the 'sort' parameter. What I want next is to allow the user instead, to supply a CODEREF for a compare routine, to allow custom sort orders.my $obj = Foo->new( sort => 1); ... while (my $val = $obj->next) {
Conventially, the way a sort compare routine receives its operands is via $a and $b, and this is what I first envisaged. But, what do these actually mean? If called from package main, these will be $main::a and $main::b - fine, but my code is looking at package Foo by default.
I could look at caller in my new routine, and export $a and $b into the caller's package name space, or import the caller's $a and $b, or hold globrefs so that I know which $a and $b are being referred to. This is messy.
I have had a discussion with a respected module author about this subject, and he sympathised with me about my plight regarding $a and $b.
I have thought up an alternative, which is for the user to supply a routine which expects the operands in @_ instead. These are nicely localised by the parameter passing mechanism, so as not to interfere with other outer sorts that may be happening. In order to make my code work, I pass in $a and $b into the called routine using an anonymous wrapper.
I clearly state in the POD that the compare routine will be passed its operands in @_. Is there anything wrong with this approach from a user perspective? If not, why should we not look to dispense with $a and $b altogether in a future perl release? I know $a and $b will be gone in perl 6, but I think that this anachronism ought to be gone sooner than that.if ($self->{sort}) { @out = (ref($self->{sort}) eq 'CODE') ? (sort {&{$self->{sort}}($a,$b)} @out) : (sort @out); }
--
I'm Not Just Another Perl Hacker
|
|---|