Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

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

by ihb (Deacon)
on Apr 18, 2005 at 23:41 UTC ( [id://449061] : note . print w/replies, xml ) Need Help??


in reply to Re^2: Making a variable in a sub retain its value between calls
in thread Making a variable in a sub retain its value between calls

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!

Replies are listed 'Best First'.
Re^4: Making a variable in a sub retain its value between calls
by tlm (Prior) on Apr 19, 2005 at 00:11 UTC

    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

      I'm talking about program run-time, not any file's run-time. If you have a module Foo that uses INIT you'll get a "Too late to run INIT block" warning if you require Foo during program run-time. E.g. you have

      # Foo.pm INIT { print 'Foo' } # foo.pl require Foo;
      That won't execute like one would hope. By using INIT to initialize variables to constants you impose a completely unnecessary constraint on your module. No module that uses your Foo can be loaded at program run-time, meaning you can't ever use Foo, directly or indirectly, in any module that is dynamically loaded (like plugin modules). That's quite a serious limitation.

      There's absolutely no reason, in general, for the initialization of the typical static variable to not happen at compile-time.

      ihb

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

        We disagree on what we consider general programming practice vs. programming for special cases, but it seems to me that this is a tomayto-tomahto difference of opinion.

        Update: Perhaps I should clarify that, most of my programming is scripting, not module-writing, and of the module writing I do, 90% of it is OO classes. In the case of scripts, INIT is perfectly fine; it gives me a hook that I know will happen after all the BEGINs I have scattered throughout my code. In my OO code I rarely if ever need static variables.

        the lowliest monk

      Since the other argument wasn't convincing enough, here's an argument that hopefully is.

      There's absolutely no reason, in general, for the initialization of the typical static variable to happen at compile time.

      Yes there is. Now, a very real-world example:

      # Foo.pm package Foo; use base 'Exporter'; our @EXPORT = qw/ foo_init foo_begin /; { my $thing; INIT { $thing = 'init' }; sub foo_init { print "init: $thing"; } } { my $thing; BEGIN { $thing = 'begin' }; sub foo_begin { print "begin: $thing"; } } 1; # Bar.pm package Bar; use Foo; # This can be put in &import if you # think that's more real-world. foo_init(); foo_begin(); 1; # foo.pl #!/usr/bin/perl -wl use Bar;
      The output of this will be
      Use of uninitialized value in concatenation (.) or string at Foo.pm li +ne 9. init: begin: begin

      Again, if you put unnecessary INITs in a module you render that module close to useless for many applications where it could've been used.

      ihb

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