Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Using sort code-refs from a different package

10 views
Skip to first unread message

Joe Casadonte

unread,
Nov 17, 2008, 8:59:21 PM11/17/08
to

I'm having trouble making some common sort code references in a module
and then using them in a different packages. I think the problem requires
the use of a closure to make it work, but I can't figure out how to do
it correctly. Here's a completely contrived example that works:

,----[ This code works ]
| #!perl -w
|
| use strict;
|
| our($SORT_ORDER) = {R => 1, Y => 2, G => 3};
| our($DECODE) = {R => 'Red', Y => 'Yellow', G => 'Green'};
| our($SORT_FN) = sub { $SORT_ORDER->{$a} <=> $SORT_ORDER->{$b} };
|
| foreach my $key (sort $SORT_FN keys %$DECODE) {
| print "$key: $DECODE->{$key}\n";
| }
`----

This produces the following (expected) output:

D:\>perl test-works.pl
R: Red
Y: Yellow
G: Green


If I put the definition of the sort function in another package, it
breaks:

,----[ This code fails miserably ]
| #!perl -w
|
| use strict;
|
| package Foo;
|
| our($SORT_ORDER) = {R => 1, Y => 2, G => 3};
| our($DECODE) = {R => 'Red', Y => 'Yellow', G => 'Green'};
| our($SORT_FN) = sub { $SORT_ORDER->{$a} <=> $SORT_ORDER->{$b} };
|
| package main;
|
| foreach my $key (sort $Foo::SORT_FN keys %$Foo::DECODE) {
| print "$key: $Foo::DECODE->{$key}\n";
| }
`----

which produces the following:

D:\>perl test-fails.pl
Name "Foo::a" used only once: possible typo at test-fails.pl line 9.
Name "Foo::b" used only once: possible typo at test-fails.pl line 9.
Use of uninitialized value in hash element at test-fails.pl line 9.
Use of uninitialized value in hash element at test-fails.pl line 9.
Use of uninitialized value in numeric comparison (<=>) at test-fails.pl line 9.
Use of uninitialized value in numeric comparison (<=>) at test-fails.pl line 9.
Use of uninitialized value in hash element at test-fails.pl line 9.
Use of uninitialized value in hash element at test-fails.pl line 9.
Use of uninitialized value in numeric comparison (<=>) at test-fails.pl line 9.
Use of uninitialized value in numeric comparison (<=>) at test-fails.pl line 9.
Use of uninitialized value in hash element at test-fails.pl line 9.
Use of uninitialized value in hash element at test-fails.pl line 9.
Use of uninitialized value in numeric comparison (<=>) at test-fails.pl line 9.
Use of uninitialized value in numeric comparison (<=>) at test-fails.pl line 9.
R: Red
G: Green
Y: Yellow


I tried making a closure out of it, thinking that there was something
funky going on with the scope of $SORT_ORDER:

,----[ This time with a closure ]
| #!perl -w
|
| use strict;
|
| package Foo;
|
| our($SORT_ORDER) = {R => 1, Y => 2, G => 3};
| our($DECODE) = {R => 'Red', Y => 'Yellow', G => 'Green'};
|
| sub make_sort
| {
| my($sort_order) = @_;
| return sub { $sort_order->{$a} <=> $sort_order->{$b} };
| }
|
| our($SORT_FN) = make_sort($SORT_ORDER);
|
|
| package main;
|
| foreach my $key (sort $Foo::SORT_FN keys %$Foo::DECODE) {
| print "$key: $Foo::DECODE->{$key}\n";
| }
`----


and it still failed:

D:\>perl test-closure.pl
Name "Foo::a" used only once: possible typo at test-closure.pl line 13.
Name "Foo::b" used only once: possible typo at test-closure.pl line 13.
Use of uninitialized value in hash element at test-closure.pl line 13.
Use of uninitialized value in hash element at test-closure.pl line 13.
Use of uninitialized value in numeric comparison (<=>) at test-closure.pl line 13.
Use of uninitialized value in numeric comparison (<=>) at test-closure.pl line 13.
Use of uninitialized value in hash element at test-closure.pl line 13.
Use of uninitialized value in hash element at test-closure.pl line 13.
Use of uninitialized value in numeric comparison (<=>) at test-closure.pl line 13.
Use of uninitialized value in numeric comparison (<=>) at test-closure.pl line 13.
Use of uninitialized value in hash element at test-closure.pl line 13.
Use of uninitialized value in hash element at test-closure.pl line 13.
Use of uninitialized value in numeric comparison (<=>) at test-closure.pl line 13.
Use of uninitialized value in numeric comparison (<=>) at test-closure.pl line 13.
R: Red
G: Green
Y: Yellow


So either I didn't do the closure correctly or I'm barking up the
wrong tree completely. Can anyone hand me a clue-stick, please?

Thanks!

--
Regards,


joe
Joe Casadonte
jcasa...@northbound-train.com

------------------------------------------------------------------------------
Llama Fresh Farms => http://www.northbound-train.com
Ramblings of a Gay Man => http://www.northbound-train.com/ramblings
Emacs Stuff => http://www.northbound-train.com/emacs.html
Music CD Trading => http://www.northbound-train.com/cdr.html
------------------------------------------------------------------------------
Live Free, that's the message!
------------------------------------------------------------------------------

Yitzchak Scott-Thoennes

unread,
Nov 18, 2008, 7:58:54 PM11/18/08
to
On Mon, November 17, 2008 5:59 pm, Joe Casadonte wrote:
> I'm having trouble making some common sort code references in a module
> and then using them in a different packages.

In order to make that work, you can put a $$ prototype on your compare
routine and sort will pass the values instead of using $a and $b.
At least in non-ancient perls.

Brian McCauley

unread,
Nov 20, 2008, 4:14:43 PM11/20/08
to
On 18 Nov, 01:59, "Joe Casadonte" <jcasado...@northbound-train.com>
wrote:

> I'm having trouble making some common sort code references in a module
> and then using them in a different packages.

> | sub make_sort


> | {
> |       my($sort_order) = @_;
> |       return sub { $sort_order->{$a} <=> $sort_order->{$b} };
> | }

If you lack a recent Perl (which allows you to simply use a
prototype):

sub make_sort
{
my($sort_order) = @_;

no strict 'refs';
my $r_a = \${ caller . '::a' };
my $r_b = \${ caller . '::b' };
return sub { $sort_order->{$$r_a} <=> $sort_order->{$$r_b} };
}

Ilya Zakharevich

unread,
Nov 21, 2008, 1:48:33 PM11/21/08
to
[A complimentary Cc of this posting was sent to
Joe Casadonte
<jcasa...@northbound-train.com>], who wrote in article <uljvhv...@terrapin.northbound-train.com>:

> ,----[ This code fails miserably ]
> | #!perl -w
> |
> | use strict;
> |
> | package Foo;
> |
> | our($SORT_ORDER) = {R => 1, Y => 2, G => 3};
> | our($DECODE) = {R => 'Red', Y => 'Yellow', G => 'Green'};
> | our($SORT_FN) = sub { $SORT_ORDER->{$a} <=> $SORT_ORDER->{$b} };
> |
> | package main;
> |
> | foreach my $key (sort $Foo::SORT_FN keys %$Foo::DECODE) {
> | print "$key: $Foo::DECODE->{$key}\n";
> | }
> `----

[Myself, I do not see any reason to use `our', so this is just a wild shot]

$SORT_FN is a lexical, so it has no relation to packages. Just remove Foo::

perl -wle "our $foo=12; package Bar; print $foo"
12

Hope this helps,
Ilya

0 new messages