http://qs321.pair.com?node_id=449018


in reply to Making a variable in a sub retain its value between calls

That's the way to do it in Perl, but one note of caution: your initializer isn't being executed before your loop. The declaration and sub definition happen at compile time, but the assignment is a runtime thing, and the code gets run from top to bottom. Your output is unchanged even if you initialize $memory to 'a' (which the autoincrement op should then change to b and c in turn).

You can make your enclosing block a BEGIN block, or you can put it above the rest of your code.


Caution: Contents may have been coded under pressure.

Replies are listed 'Best First'.
Re^2: Making a variable in a sub retain its value between calls
by tlm (Prior) on Apr 18, 2005 at 21:50 UTC

    Update: In the days and weeks after the debate that followed this comment of mine, through reading and CB conversations I have convinced myself that INIT blocks are not "up to spec", so I'm avoiding them. See in particular TimToady's node in this thread.


    In the TIMTOWTDI vein, I'm partial to INIT blocks myself:

    use strict; use warnings; test() for (1..3); { my $memory; INIT { $memory = 'a' } sub test { print "Value of static var is ", $memory++, "\n"; } } __END__ Value of static var is a Value of static var is b Value of static var is c
    I like using an extra internal INIT block only because it clearly sets the initialization code off from the rest.

    Of course, if one doesn't like INIT or BEGIN blocks, one can always explicitly check in test that $memory has been initialized and remedy the situation if necessary, but that's ugly, IMO.

    the lowliest monk

      I'm partial to INIT blocks myself

      Noooooooooooo! Please please please don't do that! It will break if you put the code using the INIT block in a module and that modules is directly or indirectly required (i.e., loaded after program compile-time). INITs are not executed right after the file in which it was found is done compiling. It's executed after the program file is done compiling. INIT is used when you need to do something delay execution of something to before program run-time.

      Personally I go with adding a BEGIN before the bare block, thus avoiding to retype the variable name.

      BEGIN { my $memory = 'a'; sub test { print "Value of static var is ", $memory++, "\n"; } }

      Update: added clarification.

      ihb

      See perltoc if you don't know which perldoc to read!

        Yes, but I want this initialization to happen just before run time. There's absolutely no reason, in general, for the initialization of the typical static variable to happen at compile time.

        the lowliest monk

Re^2: Making a variable in a sub retain its value between calls
by crashtest (Curate) on Apr 19, 2005 at 16:39 UTC
    Thanks for the catch! I'm not initializing the variable in my actual code, and only set $memory = 0 in my post on a whim. But it illustrated a subtlety I would have probably missed on my own. And your comment seems to have sparked a lively and interesting debate on BEGIN vs. INIT blocks.