Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
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
Node Status?
node history
Node Type: note [id://449018]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (4)
As of 2018-10-20 09:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    When I need money for a bigger acquisition, I usually ...














    Results (115 votes). Check out past polls.

    Notices?
    • (Sep 10, 2018 at 22:53 UTC) Welcome new users!