From: Jon Molin <[EMAIL PROTECTED]>
> I'm trying to use eval () with a constants module and it works very
> funny, can anyone explain this behavior to me. It seems to me as this
> is a scope thing. If i remove the 'my' it works fine but i can't see
> why it shouldn't work with my:
>
> i have a module with constants (constants.pm):
> ##############################################################
> package constants;
> my %month_number = (
> ... <snipped>
>
> sub get_constant
> {
> my $name = shift;
> my $ret = ();
> "$month_number{Dec}\n"; # <------ ODD ROW
> eval '$ret = \\%month_number';
> print "$_ -> $ret->{$_}\n" foreach (keys %{$ret}); # just to trace
> print "$ret=$ret->{Dec}\n"; # just to trace
> return $ret;
> }
> 1;
Well this is a tricky one.
If you write something like :
sub fooGen {
my $x = shift();
return sub { map {$_ + $x} @_};
}
$foo = fooGen(3);
print join(', ', &$foo(1,2,3,4,5)),"\n";
Then you've created a so called "closure". The $foo contains a
reference to a function that somehow remembers what was the
value of $x in the block where the subroutine was created.
And it doesn't only remember the VALUE, it really uses the
VARIABLE! Try this :
sub fooGen {
my $x = shift();
return sub { map {$_ + $x} @_}, sub {$x = shift;};
}
( $foo, $setfoo) = fooGen(3);
print join(', ', &$foo(1,2,3,4,5)),"\n";
&$setfoo(10);
print join(', ', &$foo(1,2,3,4,5)),"\n";
You see that those closures SHARE the variable.
The
my $var = ...;
sub Foo {
...
}
is also a closure even if it doesn't look like one (it's IMHO a
degenerated case of closure, but ...)
Now if you create a subroutine in a block where you defined a lot of
lexical variables should it remember them all? Plus all those that
were defined in the parent block, and its parent ...
That'd be pretty inefficient.
So a closure ONLY remembers those variables that are BEING
USED in it. And not the others.
So if you include that odd row the compiler knows you are using
the variable in the closure, so it remembers that variable. If you
don't ...
Jenda
P.S.: Your constants module looks strange. What do you want to
acomplish? Wouldn't it be better to use Exporter:
package constants;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(%month_number $scalarConst);
our %month_number = ( ... );
our $scalarConst = 15;
1;
and then use it like this :
use constants qw(%month_number);
Also, please don't use all-lower-case names for modules. All-lower-
case is supposed to be used only for "pragmas". For things like
"strict", "warnings", "constant" etc.
Use something like "Local::constants" or "JonMolin::constants".
P.P.S.: If you did not understand what am I talking about in this
mail, don't worry. And if you really only want to have a module with
some constants, use the Exporter method.
=========== [EMAIL PROTECTED] == http://Jenda.Krynicky.cz ==========
There is a reason for living. There must be. I've seen it somewhere.
It's just that in the mess on my table ... and in my brain.
I can't find it.
--- me
--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]