Click here to get back home

Sort::Maker : anonymous sub is compiled outside of my module

 HomeNewsGroups | Search | About
 comp.lang.perl.modules    Post an article   get this group's latest topics as an RSS feed add this group's latest topics to your My MSN content add this group's latest topics to your My Yahoo content
Subject Author Date
Sort::Maker : anonymous sub is compiled outside of my module Mumia W. (reading news) 12-05-2006
---> Sort::Maker - benchmark Gunnar Hjalmars...12-05-2006
Posted by Mumia W. (reading news) on December 5, 2006, 2:55 pm
Please log in for more thread options


On 12/05/2006 10:49 AM, harryfmudd [AT] comcast [DOT] net wrote:
> Mumia W. (reading news) wrote:
>> I wanted to see how Sort::Maker could be used to sort the "meascodes"
>> in this message:
>>
>>
http://groups.google.com/groups?selm=1165272390.675288.234670@79g2000cws.googlegroups.com
>> [...]
>>
>> Evidently, there is a bug/undocumented feature that causes an
>> anonymous sub that the programmer writes in his package to be compiled
>> in Sort::Maker, and Sort::Maker seems to make some modifications to
>> the *text* of that subroutine before it's compiled :O
>> [...]
>
> Well, it's quasi-documented. The third paragraph in "Key Extraction
> Code" about 60% of the way down the POD says "If a CODE reference is
> used, then the B::Deparse module is used to deparse it back into Perl
> source. [...]

Gotcha. With that information, I decided to try a string rather than a
CODE reference:

use strict;
use warnings;
use Data::Dumper;
use Sort::Maker;
no warnings 'once';

our $cost_order = 'A2yB';
my @sorted;

my $ms = [
'<table><tr><td meascode=\'y\'> </td></tr></table>',
'<table><tr><td meascode=\'B\'> </td></tr></table>',
'<table><tr><td meascode=\'2\'> </td></tr></table>',
'<table><tr><td meascode=\'A\'> </td></tr></table>'
];

my $sorter = make_sorter(
plain => string => q{
if (/meascode='(.)'/)
},
);
if ($@) { print "$@\n"; exit; }
@sorted = $sorter->(@$ms);
print Dumper(\@sorted);

__END__

And it works.

TIMTOWAROUND



--
paduille.4060.mumia.w@earthlink.net

Posted by Uri Guttman on December 5, 2006, 3:17 pm
Please log in for more thread options


writes:

MW(n> Gotcha. With that information, I decided to try a string rather than a
MW(n> CODE reference:

MW(n> our $cost_order = 'A2yB';
MW(n> my @sorted;


MW(n> my $sorter = make_sorter(
MW(n> plain => string => q{
MW(n> if (/meascode='(.)'/)
MW(n> },

that is using a global which can be dangerous. see my other post for a
proper solution. also it shows a cleaner bit of key extraction
code. that code uses the last expression of an if block for its value
which is naughty IMO. and if the regex fails what do you do? hell, my
example doesn't even check that too. but it does make that code into a
proper expression with && and not the if block (which is also slower).

MW(n> And it works.

good!

MW(n> TIMTOWAROUND

and some are better than others! :)

uri

--
Uri Guttman ------ uri@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org

Posted by Uri Guttman on December 5, 2006, 2:38 pm
Please log in for more thread options


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='(.)'/)
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 * = \&COST_ORDER;
MW(n> 149 if (/meascode='(.)'/)

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;',
                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@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org

Posted by Mumia W. (reading news) on December 5, 2006, 4:12 pm
Please log in for more thread options


On 12/05/2006 01:38 PM, Uri Guttman wrote:
> [...]
> 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) },
> ) ;
> [...]

It's a little more interesting if a CODE reference is used since only a
CODE ref is deparsed:

number => sub { /code="(.)"/ && index($cost_order,$1) },

But it does work the same way.


--
paduille.4060.mumia.w@earthlink.net


Posted by Uri Guttman on December 5, 2006, 5:31 pm
Please log in for more thread options


writes:

MW(n> On 12/05/2006 01:38 PM, Uri Guttman wrote:
>> [...]
>> 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) },
>> ) ;
>> [...]

MW(n> It's a little more interesting if a CODE reference is used since only
MW(n> a CODE ref is deparsed:

MW(n> number => sub { /code="(.)"/ && index($cost_order,$1) },

MW(n> But it does work the same way.

did you try that? when i do i get that $cost_order is not declared in
the internal eval. the dumped source code shows that. the reason i
didn't wan't to support just calling the code refs was for speed. the
code ref would need to be called for each sort element and that is a
sizeable extra overhead compared to running the code inline as it does
now. maybe an option can be added to call the coderef instead of
deparsing it so you can use closures for key extractions. shouldn't be
too hard to do. it would be 1 option to parse, pod for it, and a small
conditional and code generation change. wanna tackle it? :)

uri

--
Uri Guttman ------ uri@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org

Similar ThreadsPosted
ANNOUNCE: Sort::Maker .02 September 2, 2004, 5:09 am
Accomodate for poor db design using Sort::Maker? December 9, 2006, 12:48 am
Sort::Maker: style => 'plain' difficulty December 14, 2006, 4:35 am
Sort::Maker: (Notes) The plain and the orcish don't include the "init_code" December 14, 2006, 7:32 am
Pre-compiled SSL Perl modules August 6, 2006, 7:11 am
Using Set::Object - evidently I need compiled code? March 31, 2008, 10:21 pm
[ANN] Sort::Key 0.02 April 28, 2005, 11:02 am
Compiled .exe of Perl does not work when using Crypt::SSLeay May 14, 2007, 7:35 pm
Running compiled Inline C perl scripts on more than one machine February 9, 2006, 12:12 pm
unusual behaviour of perl script compiled with perlapp on hp-ux11i May 8, 2005, 7:52 am

Our other projects:

Art Dolls, Fairies and Mermaids - Sunnyfaces.net

Roy's Linux, Programming and Search Engines messages

1-Script XML SitemapXML Sitemap