moderated >> Using sort code-refs from a different package

by Joe Casadonte » Tue, 18 Nov 2008 09:59:21 GMT


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!


joe
Joe Casadonte
XXXX@XXXXX.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!
------------------------------------------------------------------------------

moderated >> Using sort code-refs from a different package

by Yitzchak Scott-Thoennes » Wed, 19 Nov 2008 08:58:54 GMT



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.

moderated >> Using sort code-refs from a different package

by Brian McCauley » Fri, 21 Nov 2008 05:14:43 GMT

On 18 Nov, 01:59, "Joe Casadonte" < XXXX@XXXXX.COM >


> | return sub { $sort_>rder->{&<t;a} <=> $sort_>rder->{$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_>rder->{$$r&<t;a} <=> $sort_>rder->{$$r_b} };
}

moderated >> Using sort code-refs from a different package

by Ilya Zakharevich » Sat, 22 Nov 2008 02:48:33 GMT

[A complimentary Cc of this posting was sent to
Joe Casadonte
< XXXX@XXXXX.COM >], who wrote in article < XXXX@XXXXX.COM >:

[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

Similar Threads

1. Code does work in different packages only

Hi folks,

While looking at the code in vars.pm (the "use vars" pragma), I tried to 
reproduce its behaviour:

use strict;
use vars $x;
$x = 3;

by writing:

use strict;
BEGIN {
 *main::x = \$main::x;
}
$x = 3;

instead. However, this code doesnt work, I get the messages

Variable "$x" not imported at line 5
Global symbol "$x" requires explicit package name at line 5

(Line 5 contains the assignment to scalar $x)

However, when including a "package hugo;" in the BEGIN block (or even 
outside, and a "package main;" thereafter), the code works as expected. It 
also works when the BEGIN block runs in package "main" and the scalar 
assignment in a different package. It fails, whenever both assignments 
(typeglob and scalar) are executed in the same package.

Can someone explain why? The typeglob assignment occurs full-qualified,  so 
it shouldn't matter which package is currently active. However, it does. 
Why?

Thanks for your answers and kind greetings from Vienna,

Ferry 


2. sorting multiple different entries using Perl - Perl

3. Can't sort error out; strict refs

4. sort and Sub Refs

5. Using cell refs in Excel hyperlinks.

Is this possible?  This would be so useful!!

6. copy package from different machine - Perl

7. passing hash data from one subroutine to another using refs

Hi

Would someone please clear up / help me understand this.

I have a hash

my %allTariffData = {};

and in my sub

I have
my %tariffData = {};
	do the processing etc
	and then
return \%tariffData;

I now would like to use that data that in tariffData in another subroutine.

Would anyone be so kind as to share how I would go about this.

I can pass the whole hash, but that would not be right.

Kind Regards and thanks in advance
Brent Clark


8. Calling functions using variable (I mean symbolic refs) - Perl