variables that won't stay shared

C

cartercc

I have a big glob of data that I'm extracting from a database using
selectall_hashref(). I'm using the primary key to manipulate the data
but I have to print out the data sorted by date, not the primary key.
Here's the relevant portion of the code:

sub output
(
....
foreach my $key (sort bydate keys %{$calendarhash})
{
....
print qq($calendarhash->{$key}{'calid'} $calendarhash->{$key}
{'event'} $calendarhash->{$key}{'eventdate'} $calendarhash->{$key}
{'addby'} $calendarhash->{$key}{'adddate'} \n);
....
}
#----------bydate------------------
sub bydate
{
my $date_a = $calendarhash->{$a}{'eventdate'};
my $date_b = $calendarhash->{$b}{'eventdate'};
return $date_a cmp $date_b;
}
#---------------------------------
}

Here's the error message using diagnostics:

$ perl -cw console
Variable "$calendarhash" will not stay shared at CONSOLE.pm line 191
(#1)
(W closure) An inner (nested) named subroutine is referencing a
lexical variable defined in an outer subroutine.

When the inner subroutine is called, it will probably see the
value of
the outer subroutine's variable as it was before and during the
*first*
call to the outer subroutine; in this case, after the first call
to the
outer subroutine is complete, the inner and outer subroutines will
no
longer share a common value for the variable. In other words, the
variable will no longer be shared.

Furthermore, if the outer subroutine is anonymous and references a
lexical variable outside itself, then the outer and inner
subroutines
will never share the given variable.

This problem can usually be solved by making the inner subroutine
anonymous, using the sub {} syntax. When inner anonymous subs
that
reference variables in outer subroutines are called or referenced,
they
are automatically rebound to the current values of such variables.

[Mon Mar 2 13:58:38 2009] CONSOLE.pm: Variable "$calendarhash" will
not stay shared at CONSOLE.pm line 191.
Variable "$calendarhash" will not stay shared at MUPD.pm line 209 (#1)
[Mon Mar 2 13:58:38 2009] MUPD.pm: Variable "$calendarhash" will not
stay shared at MUPD.pm line 209.
console syntax OK
$

I want to place the bydate() function WITHIN the lexical scope of the
display function, and can't understand why Perl complains. (Actually,
I can understand why Perl complains, I just can't understand why it
SHOULD complain.)

Is this error message significant? If so, should I remove the bydate()
function from the scope of the display function? I don't care to use
an anonymous function as I feel that it needlessly obscures the code,
and I want to keep the sorting function in the main function for the
same reason.

Thanks, CC.
 
A

A. Sinan Unur

Quoth cartercc <[email protected]>:


Yes, it's absolutely significant. A cutdown version of your code with
enough program round it to test it might look like:

#!/usr/bin/perl -l

sub output {
my $calendarhash = { @_ };

foreach my $key (sort bydate keys %{$calendarhash}) {
print $key;
}

sub bydate {
my $date_a = $calendarhash->{$a};
my $date_b = $calendarhash->{$b};
return $date_a cmp $date_b;
}
}

<snip output illustrating wrong results>

An alternative if the comparator is long and one does not want to inline
it with the sort call would be to use:

#!/usr/bin/perl -l

use strict;
use warnings;

sub output {
my $cal = { @_ };

my $bydate_comparator = sub {
my $date_a = $cal->{$a};
my $date_b = $cal->{$b};
return $date_a cmp $date_b;
};

for my $key (sort $bydate_comparator keys %$cal) {
print $key;
}
return;
}

print "FIRST TIME:";
output a => 1, b => 2;

print "SECOND TIME:";
output a => 2, b => 1;

__END__

E:\Home\asu1\Downloads> t.pl
FIRST TIME:
a
b
SECOND TIME:
b
a

--
A. Sinan Unur <[email protected]>
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://www.rehabitation.com/clpmisc/
 
C

ccc31807

Thanks, Ben and Sinan. I've adopted the inline solution.

Yes, it's absolutely significant. A cutdown version of your code with
enough program round it to test it might look like:

Yes, I was too dense to see it, but I understand it now. My mind just
wasn't tracking with the diagnostics message.

What exactly do you think is wrong with

    foreach my $key (
        sort {
            $calendarhash->{$a}{...} cmp $calendarhash->{$b}{....}
        } keys %{$calendarhash}
    ) {

There's nothing wrong with it. I usually like to use a style where I
place repeated code in named blocks that return values, IOW,
functions.

Thinking about this globally, I guess what I was thinking was that I
would use a private method in the module (I have two, one named
CONSOLE.pm and the other MUPD.pm). I know very little about OO Perl,
so my question would be if you can't use internal functions, how would
you write a private method in Perl? With Java, you can embed both
internal methods and internal classes, and in C++ you can use friend
functions as well as internal functions.

CC
 
C

ccc31807

Perl has a very minimal OO system, and one of the things it doesn't
provide natively is private methods. If you're learning Perl OO starting
now, and you are expecting it to look like other OO languages you've
come across, you may want to start out learning to use Moose rather than
the native OO. It's a little heavy, but it provides a very complete
object model similar to the one that will be in Perl 6.

I am contemplating redoing in an OO style a scheduling application I
built several years ago. The app doesn't need redoing, and there are
several CPAN modules I could use for it, but my motivation is to learn
more about OO Perl than I know, and the only way you can learn
something is to practice it. I'll probably get about 10K messages
about not-reinventing-the-wheel when I start posting my help messages.

In the past year or so, I've had some heavy experience with Java, C++,
and Lisp, along with using Perl on a daily basis. It's become common
for me to experience a frustrating few minutes up to an hour trying to
'fix' non-working code when it dawns on me, 'Oops, wrong language.'
This has been an educational process, and I might start verbalizing
about in on c.l.p.m., but for now I'll relate the most astonishing
moment I've had!

I'm working through Wilensky's book 'Common Lispcraft' (1984) doing
the exercises at the end of each chapter. At the end of chapter 7, one
of the exercises is to build a working inheritance hierarchy. At the
end of chapter 8 we are asked to implement polymorphism. These
exercises don't use pre-built functionality like you do in Java (for
example) by extending or implementing a class -- the student builds
them natively using the core capabilities of the language.

Now, in which programming text in what programming language are you
expected to implement inheritance hierarchies and polymorphism in
chapters 7 and 8 of the basic text? Lisp is a language from the 1950s
yet could do stuff in the mid-1980s that the BIG languages can't yet
do! Put this in your pipe and smoke it!

CC
 

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,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top