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, 8:25 am
Please log in for more thread options


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

To do this, I wrote this program:

132 use strict;
133 use warnings;
134 use Data::Dumper;
135 use Sort::Maker;
136
137 my $cost_order = 'A2yB';
138 my @sorted;
139
140 my $ms = [
141 '<table><tr><td meascode=\'y\'> </td></tr></table>',
142 '<table><tr><td meascode=\'B\'> </td></tr></table>',
143 '<table><tr><td meascode=\'2\'> </td></tr></table>',
144 '<table><tr><td meascode=\'A\'> </td></tr></table>'
145 ];
146
147 my $sorter = make_sorter(
148 plain => string => sub {
149 if (/meascode='(.)'/)
150 },
151 );
152 if ($@) { print "$@\n"; exit; }
153 @sorted = $sorter->(@$ms);
154 print Dumper(\@sorted);

However, this fails with "Global symbol "$cost_order" requires explicit
package name at (eval 12) line 8."

I was a little surprised, since anonymous subs usually have access to
lexical variables. I decided to make $cost_order a package variable (in
main) and fully qualify it as $::cost_order in the anonymous sub, so I
changed the lines of the program like so:

137 our $cost_order = 'A2yB';
149 if (/meascode='(.)'/)

However, it fails again with the same error message as before.
Thankfully, it prints out the key extraction code which shows that my
colons have been removed from $::cost_order, and even when I use
$main::cost_order, it gets changed to $cost_order--which causes the failure.

I then decided to change the variable $cost_order to a subroutine:

137 sub COST_ORDER { 'A2yB' }
149 if (/meascode='(.)'/)

And I get this error message: "Undefined subroutine
&Sort::Maker::COST_ORDER called at (eval 12) line 8."

It looks like my anonymous sub is being compiled in Sort::Maker. No
problem, I'll just put the qualifiers on the COST_ORDER():

149 if (/meascode='(.)'/)

But it fails with the same error message. I can only assume that the
colons were stripped from COST_ORDER() before the anonymous sub was
compiled. Finally, I had an insight: Sort::Maker likes stuff to be in
its package, so I try this:

137 sub COST_ORDER { 'A2yB' }
146 * = \&COST_ORDER;
149 if (/meascode='(.)'/)

And it works.

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

Perl 5.8.4
Sort::Maker 0.05
Debian 3.1 (i686)


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

Posted by Gunnar Hjalmarsson on December 5, 2006, 11:11 am
Please log in for more thread options


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

Interesting! I was waiting for Uri to jump in again, but you were first. :)

> To do this, I wrote this program:
>
> 132 use strict;
> 133 use warnings;
> 134 use Data::Dumper;
> 135 use Sort::Maker;
> 136
> 137 my $cost_order = 'A2yB';
> 138 my @sorted;
> 139
> 140 my $ms = [
> 141 '<table><tr><td meascode=\'y\'> </td></tr></table>',
> 142 '<table><tr><td meascode=\'B\'> </td></tr></table>',
> 143 '<table><tr><td meascode=\'2\'> </td></tr></table>',
> 144 '<table><tr><td meascode=\'A\'> </td></tr></table>'
> 145 ];
> 146
> 147 my $sorter = make_sorter(
> 148 plain => string => sub {
> 149 if (/meascode='(.)'/)
> 150 },
> 151 );
> 152 if ($@) { print "$@\n"; exit; }
> 153 @sorted = $sorter->(@$ms);
> 154 print Dumper(\@sorted);
>
> However, this fails with "Global symbol "$cost_order" requires explicit
> package name at (eval 12) line 8."

That error can be fixed by passing the var to the sub:

plain => string => sub {
if ( /meascode='(.)'/ ) { index( $_[0], $1 ) }
}->($cost_order),

But it didn't give the correct output...

--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl

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



GH> 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

GH> Interesting! I was waiting for Uri to jump in again, but you were first. :)

i did jump in. just took some time.

GH> That error can be fixed by passing the var to the sub:

GH> plain => string => sub {
GH> if ( /meascode='(.)'/ ) { index( $_[0], $1 ) }
GH> }->($cost_order),

GH> But it didn't give the correct output...

that is calling the sub IMMEDIATELY and passing its return value to the
make_sorter sub as the arg of the 'string' option. very bad. when you
are not sure about how Make::Sorter is working, print out the generated
sub with sorter_source. see my other posting for more and the correct
way to do this.

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 harryfmudd [AT] comcast [DOT] on December 5, 2006, 11:49 am
Please log in for more thread options


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
>
>
> To do this, I wrote this program:
>
> 132 use strict;
> 133 use warnings;
> 134 use Data::Dumper;
> 135 use Sort::Maker;
> 136
> 137 my $cost_order = 'A2yB';
> 138 my @sorted;
> 139
> 140 my $ms = [
> 141 '<table><tr><td meascode=\'y\'> </td></tr></table>',
> 142 '<table><tr><td meascode=\'B\'> </td></tr></table>',
> 143 '<table><tr><td meascode=\'2\'> </td></tr></table>',
> 144 '<table><tr><td meascode=\'A\'> </td></tr></table>'
> 145 ];
> 146
> 147 my $sorter = make_sorter(
> 148 plain => string => sub {
> 149 if (/meascode='(.)'/)
> 150 },
> 151 );
> 152 if ($@) { print "$@\n"; exit; }
> 153 @sorted = $sorter->(@$ms);
> 154 print Dumper(\@sorted);
>
> However, this fails with "Global symbol "$cost_order" requires explicit
> package name at (eval 12) line 8."
>
> I was a little surprised, since anonymous subs usually have access to
> lexical variables. I decided to make $cost_order a package variable (in
> main) and fully qualify it as $::cost_order in the anonymous sub, so I
> changed the lines of the program like so:
>
> 137 our $cost_order = 'A2yB';
> 149 if (/meascode='(.)'/)
>
> However, it fails again with the same error message as before.
> Thankfully, it prints out the key extraction code which shows that my
> colons have been removed from $::cost_order, and even when I use
> $main::cost_order, it gets changed to $cost_order--which causes the
> failure.
>
> I then decided to change the variable $cost_order to a subroutine:
>
> 137 sub COST_ORDER { 'A2yB' }
> 149 if (/meascode='(.)'/)
>
> And I get this error message: "Undefined subroutine
> &Sort::Maker::COST_ORDER called at (eval 12) line 8."
>
> It looks like my anonymous sub is being compiled in Sort::Maker. No
> problem, I'll just put the qualifiers on the COST_ORDER():
>
> 149 if (/meascode='(.)'/)
>
> But it fails with the same error message. I can only assume that the
> colons were stripped from COST_ORDER() before the anonymous sub was
> compiled. Finally, I had an insight: Sort::Maker likes stuff to be in
> its package, so I try this:
>
> 137 sub COST_ORDER { 'A2yB' }
> 146 * = \&COST_ORDER;
> 149 if (/meascode='(.)'/)
>
> And it works.
>
> 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
>
> Perl 5.8.4
> Sort::Maker 0.05
> Debian 3.1 (i686)
>
>

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. This source is then used to extract the key in the generated
sorter. As with qr//, the advantage is that the extraction code is
syntax checked at compile time and not runtime. Also the deparsed code
is wrapped in a do{} block so you may use complex code to extract the key."

So it's not, strictly speaking, undocumented, but I admit that I find it
an un-Perlish behaviour. His "the advantage is that the extraction code
is syntax checked at compile time and not runtime" seems a bit
irrelevant; if you have a code reference to pass in the first place, it
seems to me that we already know it compiles.

It would seem to me that the author could have done something like
returning the code reference as-is, and made his sort routine call that.
But then, I'm not writing the code.

Tom Wyant

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


>>>>> "h[c[n" == harryfmudd [AT] comcast [DOT] net <harryfmudd> writes:

h[c[n> Well, it's quasi-documented. The third paragraph in "Key Extraction
h[c[n> Code" about 60% of the way down the POD says "If a CODE reference is
h[c[n> used, then the B::Deparse module is used to deparse it back into Perl
h[c[n> source. This source is then used to extract the key in the generated
h[c[n> sorter. As with qr//, the advantage is that the extraction code is
h[c[n> syntax checked at compile time and not runtime. Also the deparsed code
h[c[n> is wrapped in a do{} block so you may use complex code to extract the
h[c[n> key."

you are looking for the wrong feature. see my other posts for the
correct way to use this module here.

h[c[n> So it's not, strictly speaking, undocumented, but I admit that I find
h[c[n> it an un-Perlish behaviour. His "the advantage is that the extraction
h[c[n> code is syntax checked at compile time and not runtime" seems a bit
h[c[n> irrelevant; if you have a code reference to pass in the first place,
h[c[n> it seems to me that we already know it compiles.

you are not interpreting that correctly so it may need a rewrite. the
comparison there is between a a key extraction which is a string of code
vs a code reference (typically an anon sub right there). then the sub
will be compiled at compile time vs much later at runtime when
make_sorter is called. so with an anon sub you will see any syntax
errors immediately vs. in the error output of make_sorter. this is a
nice win and it is due to damian conway asking for it (and showing me
how to deparse a code ref).

h[c[n> It would seem to me that the author could have done something like
h[c[n> returning the code reference as-is, and made his sort routine call
h[c[n> that. But then, I'm not writing the code.

you can't do that with the current module. there would need to be a way
to access the code ref at sorting time and that would need the sorter to
be a closure or use some private hash to track code refs. i may examine
these approaches but they don't offer any speedup or major wins
IMO. using the method i showed in another post solves this problem very
easily.

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