Question re Conway's "Perl Best Practices" - Sort::Maker

U

usenet

Uri reminded me (in another thread: http://tinyurl.com/nyclh) of his
module, Sort::Maker, which Damian Conway praised in "Perl Best
Practices" (page 164-165), and which I have been meaning to learn more
about.

However, I am having difficulty with Damian's example.

Kindly consider this small sample program wrapped around some PBP
example code which I have retyped verbatum (adding only my own
statement to populate sample @names):

#!/usr/bin/perl
use strict; use warnings;
use Sort::Maker;

my @names = qw{ Fred Barney Wilma Betty };

make_sorter(name => 'sort_len', code => sub{ length }, ST => 1);
# and later...
my @names_shortest_first = sort_len(@names);

__END__

The script fails with:
Undefined subroutine &main::sort_len...

But, according to the Sort::Maker perldocs, 'name' is
So I believe that sort_len should be exported when the make_sorter
statement is executed. But it doesn't seem to be working.

What am I doing wrong?

(perl, v5.8.4 built for aix, $Sort::Maker::VERSION == 0.05)
 
D

DJ Stunks

Uri reminded me (in another thread: http://tinyurl.com/nyclh) of his
module, Sort::Maker, which Damian Conway praised in "Perl Best
Practices" (page 164-165), and which I have been meaning to learn more
about.

However, I am having difficulty with Damian's example.

Kindly consider this small sample program wrapped around some PBP
example code which I have retyped verbatum (adding only my own
statement to populate sample @names):

#!/usr/bin/perl
use strict; use warnings;
use Sort::Maker;

my @names = qw{ Fred Barney Wilma Betty };

make_sorter(name => 'sort_len', code => sub{ length }, ST => 1);
# and later...
my @names_shortest_first = sort_len(@names);

__END__

The script fails with:
Undefined subroutine &main::sort_len...

But, according to the Sort::Maker perldocs, 'name' is

So I believe that sort_len should be exported when the make_sorter
statement is executed. But it doesn't seem to be working.

What am I doing wrong?

(perl, v5.8.4 built for aix, $Sort::Maker::VERSION == 0.05)

Well, the first thing I did was grab my copy of _PBP_ and check that
you weren't nuts. Which you aren't :)

The second thing I did was run your sample code, with the same results.

I then added an error check on the make_sorter call and it died with
the error:
Unable to create sorter: make_sorter: Unknown option or key 'code'

So then I had a look at the docs (which I hadn't ever looked at before)
and managed to munge up the following, which works.

I'm sure Pastor Conway ran all the code in his book, so maybe something
changed. Only Uri knows for sure.

-jp

#!/usr/bin/perl
use strict; use warnings;

use Sort::Maker;

my @names = qw{ Fred Barney Wilma Betty };

make_sorter(
qw( ST ),
name => 'sort_len',
string => {
code => sub { length }
}
) or die "Unable to create sorter: $@";

print join "\n", sort_len(@names);

__END__
 
U

Uri Guttman

DS> So then I had a look at the docs (which I hadn't ever looked at before)
DS> and managed to munge up the following, which works.

DS> I'm sure Pastor Conway ran all the code in his book, so maybe something
DS> changed. Only Uri knows for sure.

DS> -jp

DS> #!/usr/bin/perl
DS> use strict; use warnings;

DS> use Sort::Maker;

DS> my @names = qw{ Fred Barney Wilma Betty };

DS> make_sorter(
DS> qw( ST ),
DS> name => 'sort_len',
DS> string => {
DS> code => sub { length }
DS> }
DS> ) or die "Unable to create sorter: $@";

DS> print join "\n", sort_len(@names);


from the Changes file:

0.04 Wed Apr 27 01:37:00 EDT 2005
- fixed 'name' option bug, added test and docs
-from Damian Conway <[email protected]>

so he found that bug and this was during the tech review period of PBP
so i think the fix didn't get propogated back to the book. in any case
you should always trust up to date docs in a module than any dead trees
book that mentions a module and shows examples on how to use it.

the best thing to do now is email damian and report this errata so he
could put it in his errata page and possibly get it fixed in a future
printing or edition.

uri
 
U

usenet

Uri said:
the best thing to do now is email Damian and report this errata

Thanks for your reply, Uri. I have submitted an errata report on the
O'Reilly website, as they provide an easy mechanism to facilitate this.
 
R

Randal L. Schwartz

Uri> the best thing to do now is email damian and report this errata so he
Uri> could put it in his errata page and possibly get it fixed in a future
Uri> printing or edition.

Please don't "email the author" for an O'Reilly book to report errata.
O'Reilly's web page for a given book has a clearly marked "report and see
errata for this book" link. Use that instead.

Part of the services of a major publisher is to track and update errata, so
that the author does not need to do that directly. I'm surprised Uri was
unaware of that.

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<[email protected]> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!

*** ***
 
S

Salvador Fandino

Uri reminded me (in another thread: http://tinyurl.com/nyclh) of his
module, Sort::Maker, which Damian Conway praised in "Perl Best
Practices" (page 164-165), and which I have been meaning to learn more
about.

However, I am having difficulty with Damian's example.

Kindly consider this small sample program wrapped around some PBP
example code which I have retyped verbatum (adding only my own
statement to populate sample @names):

#!/usr/bin/perl
use strict; use warnings;
use Sort::Maker;

my @names = qw{ Fred Barney Wilma Betty };

make_sorter(name => 'sort_len', code => sub{ length }, ST => 1);
# and later...
my @names_shortest_first = sort_len(@names);

__END__

you would probably want to have a look at Sort::Key module also. It is
usually faster than Sort::Maker and IMO easier to use.

For instance to sort by length:

use Sort::Key qw(ikeysort);

my @names = qw{ Fred Barney Wilma Betty };
my @names_shortest_first = ikeysort { length } @names;

or alternatively:

use Sort::Key::Maker sort_len => sub { length }, qw(integer);

my @names = qw{ Fred Barney Wilma Betty };
my @names_shortest_first = sort_len @names;

Cheers,

- Salva
 
U

Uri Guttman

SF> you would probably want to have a look at Sort::Key module also. It is
SF> usually faster than Sort::Maker and IMO easier to use.

i find the massive number of different exported functions, including
ones created on the fly to be more confusing. but timtowtdi rules apply.

as for faster, your module appears to do its key extractions and
compares in each compare block which are O(N log N). the GRT and ST
(both of which can be used in sort::maker) factor out the extractions
and makes them O(N) and that can be a major savings in large complex
sorts. so stating a module is usually faster than another should be
qualified with what criteria are used to compare them.

SF> For instance to sort by length:

SF> use Sort::Key qw(ikeysort);

SF> my @names = qw{ Fred Barney Wilma Betty };
SF> my @names_shortest_first = ikeysort { length } @names;

as i said above the multiple exported subs is not a style i like. also a
single exported sub with a well defined arg list can be more easily used
to autogenerated sort subs from a record description.

finally, sort::maker comes with a table driven test and benchmark
system. it should be easy for you to run it on your module and then we
can benchmark a wide range of datasets and sorts and see how the
different modules behave. i am very interested in seeing some apples to
apples results.

uri
 
S

Salvador Fandino

Uri said:
SF> you would probably want to have a look at Sort::Key module also. It is
SF> usually faster than Sort::Maker and IMO easier to use.

i find the massive number of different exported functions, including
ones created on the fly to be more confusing. but timtowtdi rules apply.

as for faster, your module appears to do its key extractions and
compares in each compare block which are O(N log N).

No, keys are precomputed before sorting
the GRT and ST
(both of which can be used in sort::maker) factor out the extractions
and makes them O(N) and that can be a major savings in large complex
sorts. so stating a module is usually faster than another should be
qualified with what criteria are used to compare them.

Sort::Key is faster than the ST or GRT sorting arrays of any lenght in
most cases. Only for some rare cases of key type combinations and data
could be the GRT a bit faster, but most of the times is the other way
SF> For instance to sort by length:

SF> use Sort::Key qw(ikeysort);

SF> my @names = qw{ Fred Barney Wilma Betty };
SF> my @names_shortest_first = ikeysort { length } @names;

as i said above the multiple exported subs is not a style i like. also a
single exported sub with a well defined arg list can be more easily used
to autogenerated sort subs from a record description.

that functionality is also available from the Sort::Key::Maker module.
You can create new sorters on the fly just defining the types of the keys:

use Sort::Key::Maker my_sort => qw(number -number string);

my @sorted = my_sort { $_->{foo}, $_->{bar}, $_->{doz} } @data;


or alternatively you can attach the keys extraction sub to the sorter:

use Sort::Key::Maker my_sort =>
sub { $_->{foo}, $_->{bar}, $_->{doz} }
qw(number -number string);

my @sorted = my_sort @data;


finally, sort::maker comes with a table driven test and benchmark
system. it should be easy for you to run it on your module and then we
can benchmark a wide range of datasets and sorts and see how the
different modules behave. i am very interested in seeing some apples to
apples results.

well, I already have some benchmark scripts of my own as for instance
the one attached:

$ for i in str num int num_str str_num; do perl ben2.pl -t $i; done

comparing sorters for str keys with 500000 elements:
s/iter sm skm sk
sm 6.58 -- -26% -28%
skm 4.85 36% -- -2%
sk 4.73 39% 3% --

comparing sorters for num keys with 500000 elements:
s/iter sm skm sk
sm 6.71 -- -71% -73%
skm 1.94 246% -- -5%
sk 1.84 265% 5% --

comparing sorters for int keys with 500000 elements:
s/iter sm skm sk
sm 5.94 -- -69% -70%
skm 1.85 221% -- -5%
sk 1.76 238% 5% --

comparing sorters for num_str keys with 500000 elements:
s/iter sm skm
sm 8.13 -- -31%
skm 5.62 45% --

comparing sorters for str_num keys with 500000 elements:
s/iter sm skm
sm 7.97 -- -35%
skm 5.17 54% --

(sm => Sort::Maker, sk => Sort::Key, skm => Sort::Key::Maker)

Cheers,

- Salvador
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top