Moron has asked for the wisdom of the Perl Monks concerning the following question:

When I was learning perl a few years ago, it took me a while to realise that 'local' was not analogous to 'static' in C. I later discovered that static storage could be set up for objects and even for package variables, but what I am yet to discover is how to make a variable static when its scope has to be limited to a subroutine defined within a single .pl file. This facility would reduce the time it takes to write certain types of one-off scripts.

To clarify what is meant by static: it's value would be preserved on return and re-entry to the subroutine in which it is scoped.

Many thanks in advance for any input!

-M

Free your mind

Replies are listed 'Best First'.
Re: static storage in a local subroutine?
by Limbic~Region (Chancellor) on Nov 23, 2005 at 13:32 UTC
        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).

        Cheers - L~R

      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!
        jeffguy,
        Ok, there are a few things to keep in mind here. The first is that named sub declarations are scoped to the current package. The only way to have a lexical sub is for it to be an anonymous code ref. The second thing to keep in mind is that program flow never returns to a point above the sub declaration to even attempt to redefine the sub - it is a naked block.

        If this doesn't answer your question, ask something a bit more specific. Better yet, play around and see if you can figure it out for yourself.

        Cheers - L~R

        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.

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

      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.

      -- Randal L. Schwartz, Perl hacker
      Be sure to read my standard disclaimer if this is a 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.

    -M

    Free your mind

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.

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...

      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.

      -M

      Free your mind

        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.