Re: static storage in a local subroutine?
by Limbic~Region (Chancellor) on Nov 23, 2005 at 13:32 UTC
|
{
my $cnt = 1;
sub get_count {
return $cnt++;
}
}
print get_count(), "\n" for 1..10;
| [reply] [d/l] |
|
|
You probably want that to be "BEGIN {" not "{", to ensure that the initialization is performed once and only once.
| [reply] |
|
|
merlyn,
You are of course correct. It is better to be safe then sorry. Unfortunately, I am a bit confused as to the behavior of the following:
#!/usr/bin/perl
use strict;
use warnings;
INITIALIZE:
{
my $cnt = 1;
sub get_count {
return $cnt++;
}
}
print get_count(), "\n" for 1..10;
goto INITIALIZE if get_count() < 15;
__END__
1..10, 12..21
Care to elaborate?
Update: Explanation from tye in the CB
The re-initialization of $cnt doesn't impact the get_count() sub because it is only defined once at compile time. It however does get re-initialized which may impact other things within the same scope but not in the sub itself. To avoid wasting resources and make the intent clear, using the BEGIN block is a good idea (which I never doubted in the first place).
| [reply] [d/l] |
|
|
I tested your code and am amazed to see it works. I don't understand!! I mean, I understand how to make a closure. But my intuition (which is apparently incorrect) says that sub get_count is redefined each time executing this block, thus capturing a new my $cnt each time. Can someone clear this up -- why doesn't this block redefine sub get_count each time?
Thanks in advance!
| [reply] |
|
|
| [reply] |
|
|
|
|
But my intuition (which is apparently incorrect) says that sub get_count is redefined each time executing this block
No, named subs are only created once, during compilation. Anonymous subs are created each time you ask for one to be created. The lexical capture happens at creation time.
Dave.
| [reply] |
Re: static storage in a local subroutine?
by davorg (Chancellor) on Nov 23, 2005 at 13:35 UTC
|
I think you probably want a lexical variable which is in a naked block which contains the function that manipulates the variable. Something like this:
{
my $count;
sub manipulate_count {
++$count;
print "manipulate_count has been called $count times\n";
}
}
Update: Yeah. And what merlyn said below.
--
< http://dave.org.uk>
"The first rule of Perl club is you do not talk about
Perl club." -- Chip Salzenberg
| [reply] [d/l] |
|
|
You need to make that "BEGIN {" not "{" to ensure that the initialization for $count happens once and only once. For example, if that code were in some sort of outer loop, you'd get $count cannot stay shared (I think), and if you had an initializer for $count, but that block were at the end of the file, "manipulate_count" would be called before $count had been initialized.
| [reply] |
Re: static storage in a local subroutine?
by Moron (Curate) on Nov 23, 2005 at 13:46 UTC
|
Thanks to both Limbic-Region and davorg -- this is precisely what I needed to know.
| [reply] |
Re: static storage in a local subroutine?
by crashtest (Curate) on Nov 23, 2005 at 14:39 UTC
|
For what it's worth, I asked a similar question some time ago that generated some interesting responses.
| [reply] |
Re: static storage in a local subroutine?
by tphyahoo (Vicar) on Nov 23, 2005 at 14:13 UTC
|
This facility would reduce the time it takes to write certain types of one-off scripts.
For example? I know this closure stuff is supposed to be useful, but I still don't quite grasp why... | [reply] |
|
|
Given that scripts tend to grow as variations in the requirement come along, it is important that they are as maintainable as possible. The use of lots of global variables for static storage causes maintenance problems because the code and variables are not in the same place, creating the need to have to search a growing amount of code to solve functionality coded in a localised place. Encapsulation is key to why O-O solves complexity and closure is a related concept.
| [reply] |
|
|
Yes, it's beginning to make sense: "Barrie Slaymaker calls closures "inside-out objects:" objects are data that have some subroutines attached to them, and closures are subroutines that have some data attached to them."
sub make_counter {
my $start = shift;
return sub { $start++ }
}
my $from_ten = make_counter(10);
my $from_three = make_counter(3);
print $from_ten->(); # 10
print $from_ten->(); # 11
print $from_three->(); # 3
print $from_ten->(); # 12
print $from_three->(); # 4
This example helped me understand a lot better. | [reply] [d/l] |