Re: Sort::Maker : anonymous sub is compiled outside of my module
- From: Uri Guttman <uri@xxxxxxxxxxxxxxx>
- Date: Tue, 05 Dec 2006 14:38:12 -0500
"MW(n" == Mumia W (reading news) <paduille.4060.mumia.w@xxxxxxxxxxxxx> writes:
MW(n> 137 my $cost_order = 'A2yB';
MW(n> 138 my @sorted;
MW(n> 139
MW(n> 140 my $ms = [
MW(n> 141 '<table><tr><td meascode=\'y\'> </td></tr></table>',
MW(n> 142 '<table><tr><td meascode=\'B\'> </td></tr></table>',
MW(n> 143 '<table><tr><td meascode=\'2\'> </td></tr></table>',
MW(n> 144 '<table><tr><td meascode=\'A\'> </td></tr></table>'
MW(n> 145 ];
MW(n> 146
MW(n> 147 my $sorter = make_sorter(
MW(n> 148 plain => string => sub {
MW(n> 149 if (/meascode='(.)'/) {index($cost_order,$1)}
MW(n> 150 },
MW(n> 151 );
MW(n> 152 if ($@) { print "$@\n"; exit; }
MW(n> 153 @sorted = $sorter->(@$ms);
MW(n> 154 print Dumper(\@sorted);
MW(n> I was a little surprised, since anonymous subs usually have access to
MW(n> lexical variables. I decided to make $cost_order a package variable
MW(n> (in main) and fully qualify it as $::cost_order in the anonymous sub,
MW(n> so I changed the lines of the program like so:
sort::maker builds a sort sub source and evals it. so that is done in
the Sort::Maker namespace as you learned later on. there is no way for
that code to see any lexicals or subs outside its space.
MW(n> 137 sub COST_ORDER { 'A2yB' }
MW(n> 146 *{Sort::Maker::COST_ORDER} = \&COST_ORDER;
MW(n> 149 if (/meascode='(.)'/) {index(COST_ORDER(),$1)}
MW(n> And it works.
MW(n> Evidently, there is a bug/undocumented feature that causes an
MW(n> anonymous sub that the programmer writes in his package to be compiled
MW(n> in Sort::Maker, and Sort::Maker seems to make some modifications to
MW(n> the *text* of that subroutine before it's compiled :O
there is a feature you missed which can help here. the 'init_code'
option allows you to put arbitrary code into the sort sub. this is
useful when you do work in one key extraction and generate multiple
keys. you can declare a temp var in init_code and assign it in one
extraction for use by later keys. in this case it can be used to set the
sort order string. this is a tested example. it prints out the sorter so
you see how the init_code is used.
#!/usr/local/bin/perl
use strict ;
use warnings ;
use Sort::Maker qw( make_sorter sorter_source ) ;
my @unsorted = (
'<table><tr><td meascode="y"></td></tr></table>',
'<table><tr><td meascode="2"></td></tr></table>',
'<table><tr><td meascode="A"></td></tr></table>',
'<table><tr><td meascode="B"></td></tr></table>',
) ;
my $sorter = make_sorter(
'GRT',
init_code => 'my $cost_order = q{A2yB};',
signed => 1,
string_data => 1,
number => q{ /code="(.)"/ && index($cost_order,$1) },
) ;
$sorter or die $@ ;
print sorter_source( $sorter ) ;
print map "$_\n", $sorter->( @unsorted ) ;
if you want the $cost_order to come from the outside, you can just use a
variable in the init_code and change it to "".
my $cost_order = 'A2yB';
my $sorter = make_sorter(
'GRT',
init_code => "my \$cost_order = '$cost_order' ;",
signed => 1,
string_data => 1,
number => q{ /code="(.)"/ && index($cost_order,$1) },
) ;
both output this:
<table><tr><td meascode="A"></td></tr></table>
<table><tr><td meascode="2"></td></tr></table>
<table><tr><td meascode="y"></td></tr></table>
<table><tr><td meascode="B"></td></tr></table>
and that appears to be the desired order.
note that i do a numeric compare on the index() value as a string compare
would fail when you get to more than 1 digit.
also see how i simplified getting the index value in the key extraction.
expressiveness like this is one of the major wins of Sort::Maker over
rolling your own sorts besides the speedup if you use the GRT.
uri
--
Uri Guttman ------ uri@xxxxxxxxxxxxxxx -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
.
- Follow-Ups:
- Re: Sort::Maker : anonymous sub is compiled outside of my module
- From: Mumia W. (reading news)
- Re: Sort::Maker : anonymous sub is compiled outside of my module
- References:
- Sort::Maker : anonymous sub is compiled outside of my module
- From: Mumia W. (reading news)
- Sort::Maker : anonymous sub is compiled outside of my module
- Prev by Date: Re: Spread***::Read special characters handling
- Next by Date: Re: Why does Tie::Simeple (scalar) work without real local data?
- Previous by thread: Re: Sort::Maker : anonymous sub is compiled outside of my module
- Next by thread: Re: Sort::Maker : anonymous sub is compiled outside of my module
- Index(es):