,----[ 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!
------------------------------------------------------------------------------
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.
> | 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} };
}
[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