Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Re: Making a variable in a sub retain its value between calls

by Roy Johnson (Monsignor)
on Apr 18, 2005 at 20:42 UTC ( #449018=note: print w/replies, xml ) Need Help??


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.
  • Comment on Re: Making a variable in a sub retain its value between calls

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.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://449018]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (3)
As of 2023-12-09 07:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    What's your preferred 'use VERSION' for new CPAN modules in 2023?











    Results (37 votes). Check out past polls.

    Notices?