http://www.perlmonks.org?node_id=369263

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

Hi all,

I'm quite used to declaring variables as follows:

my ($title, $page, $chapter);
That is, without initialising them with default values.

I also find it quite common in other people's code that I've come across.

I'm wondering, after reading about variables being set to old values under mod_perl, if it might be better in general to initialise each and every variable. So, instead of the above, we now have:

my $title = ''; my $page = 0; my $chapter = 0;
It's more work definitely but it generally makes the code more readable (for instance, if I've no idea what 'page' means, I at least know the variable $page is going to be used for some numerical value). There're probably also some gains in performance as the interpreter doesn't have to make guesses about those values.

Is it merely a preference thing? Or is one method better than the other?

I look forward to reading your views. Many thanks in advance :)

update: It's been very enlightening reading your comments on the node. It seems not initialising the variables is the normal thing to do in most circumstances. Thanks once again for your sharing :)

Replies are listed 'Best First'.
Re: To initialise or not to initialise?
by Abigail-II (Bishop) on Jun 24, 2004 at 08:42 UTC
    If context or variable name doesn't make clear what a variable means, or is used for, one should add a comment. What would be your default value for a variable that's going to hold a reference to an object? Or a variable that could hold both a string and a numerical value? And if you assign 0, does that mean the variable will only hold integers? Only non-negative integers? Any numerical value? But even if you know, what insight to the program did it give to you?

    I initialize variables only if it makes sense. I also tend to declare variables at their first use, which usually means the first time something is assigned to it - or it's done a line above the first assignment. Note that assigning default values will take time, although for larger blocks it won't matter too much:

    #!/usr/bin/perl use strict; use warnings; use Benchmark qw /cmpthese/; cmpthese -5 => { init => 'my $title = ""; my $page = 0; my $chapter = 0; $title && $page && $chapter', def => 'my ($title, $page, $chapter); $title && $page && $chapter', }; __END__ Rate init def init 1165121/s -- -38% def 1876595/s 61% --

    Abigail

Re: To initialise or not to initialise?
by davidj (Priest) on Jun 24, 2004 at 09:12 UTC
    I was schooled (in the academic sense) to initialize all variables upon declaring them. That was back in the days when Duran Duran was popular and most CS students cut their teeth on C. Initialization upon declaration was strongly encouraged simply because using uninitialized variables led to unintended (and very difficult to find) problems.

    When I began using perl about a year ago, through force of habit, I always initialized my variables. However, recently I have realized that leaving them uninitialized can greatly help in the debugging process when used in conjunction with use warnings. Getting that quite popular Use of uninitialized value message immediately lets me know that I have an error in my code (usually logical) because I am expecting the variable to have a value when, in fact, it does not. Since I have adopted this habit of leaving variables uninitialized I have noticed that it takes less time to write, test, and debug my code.

    davidj
      I come from a similar background, but I tend to initialize my variables. The reason is fairly simple - most of my variables store either strings that have been matched in a $[0-9], or flags indicating whether a match has been found in processing the file. These are set with lines like $flag = 1 if /pattern/;, or tested with lines like print "something\n" if $area eq "51"; so I need the flag to be initialised to 0.

      Most of my perl scripts are simple stdin or clipboard text processors for doing custom greps on source code or data migration files.

Re: To initialise or not to initialise?
by rinceWind (Monsignor) on Jun 24, 2004 at 10:34 UTC
    If you are not initialising the variables, they take the value undef. There are many cases when I specifically test for this:
    if (defined $foo) { .... }
    This is very different from C, where the contents of your variable are arbitrary and could contain complete garbage.

    Perl has a nice pragma called "use warnings", which spots when I have been to lazy to initialize any scalar variable I am trying to use.

    --
    I'm Not Just Another Perl Hacker

Re: To initialise or not to initialise?
by Aragorn (Curate) on Jun 24, 2004 at 10:36 UTC
    It's more work definitely but it generally makes the code more readable (for instance, if I've no idea what 'page' means, I at least know the variable $page is going to be used for some numerical value).
    If you have no idea what $page means, then, IMO, the name is not descriptive enough. If you use $page_nr, that would make it clear that it's used for a numerical value. $page could just as well contain a string with a PostScript rendition of a page.

    Arjen

      Would this be a good place to suggest using Hungarian Notation? my $lpszhwndPage;
Re: To initialise or not to initialise?
by bradcathey (Prior) on Jun 24, 2004 at 11:48 UTC
    kiat, another good question, one that I have thought about often. Here's where I'm at now. I no longer initialize with a value, unless that value is to be used immediately and/or it helps me read what I'm doing:
    my $ctr = 0; for ( 0 .. 5 ) { if ($foo[$_] eq $bar) { $ctr++; } }
    I have found there is a difference between:
    my $variable;
    and
    my $variable = "";
    or
    my $variable = 0;
    depending on usage. In summary, I don't think there can be a hard a fast rule. Like many things, it depends on context and the readibility you need.

    —Brad
    "Don't ever take a fence down until you know the reason it was put up. " G. K. Chesterton
      Hi bradcathey,
      I have found there is a difference between:
      Do you mean the difference between being defined and undefined?
      my $var1; # not printed because $var1 is not defined print "var1: $var1\n" if defined $var1; my $var2 = ''; # printed with $var2 as an empty string # output var2: print "var2: $var2\n" if defined $var2; my $var3 = 0; # printed with $var3 set to 0 # output var3: 0 print "var3: $var3\n" if defined $var3;
      cheers,
        Precisely, thanks for clearing up the terminology. And I have to apologize for not being about to think of a good example, but I have found at times I need the undefined variable, as opposed to the defined, inferring a value.

        —Brad
        "Don't ever take a fence down until you know the reason it was put up. " G. K. Chesterton
Re: To initialise or not to initialise?
by Anonymous Monk on Jun 24, 2004 at 10:34 UTC
    On the other hand it can be useful to initialise values, especially global ones, with a default value, so that if you need to debug later you could print out the variable to see if it changes.

    my ($title, $page, $chapter) = "somethingglobal";

    print ("$title");
    sub ...
    my $title = "somethingelocalhere";
    print ("$title");

    Also if you declare and initialise at the start of the program or of each sub, it is easier to read and maintain the code, especially to non-perl programmers.
      my ($title, $page, $chapter) = "somethingglobal";

      You've only initialized $title. You probably mean ... = ("somethingglobal") x 3;</pedant>

        I learn something new today, thanks Fletch :)

        Sometimes I wanted to do that but I didn't know what the syntax is.

Re: To initialise or not to initialise?
by dragonchild (Archbishop) on Jun 24, 2004 at 12:30 UTC
    . . . after reading about variables being set to old values under mod_perl . . .

    Do you even know why this happens? Do you know if this happens outside mod_perl? Has this been an issue for you in programs you've written?

    In other words, if it ain't a problem, don't fix it!

    Oh - and I don't have global variables. Just having them is a sign of logical weakness, initialized or not.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

    I shouldn't have to say this, but any code, unless otherwise stated, is untested

      Hi dragonchild,

      Do you even know why this happens? Do you know if this happens outside mod_perl? Has this been an issue for you in programs you've written?
      A little quote from my original post...
      if it might be better in general to initialise each and every variable. So, instead of the above, we now have:
      I used the words in general so I wasn't looking at any particular situation.

      It is not an issue to me, but nonetheless I was interested to hear from the experts here what the normal practice is.

      One of Perl's uniqueness is "there's more than one way to do it". I was curious to find out if there's indeed a preferred way of treating variables wrt value initialisation.

      Oh - and I don't have global variables. Just having them is a sign of logical weakness, initialized or not.

      Eh, we should be careful how we define "globals" when making such statements. Indeed in strictly procedural programs it is foolish and unnecessary to have global variables. However, what about package globals? Having in Perl what would be denoted in other languages as a "static class member" is not an unreasonable thing to do, and is often in my experience necessary.

        Those aren't globals. Those are static class members. That they are implemented as a package global is completely and utterly irrelevant. The same goes for any other CS construct you can think of that in Perl is implemented as a package- or file-scoped global. Truly global variables are good for three things only:
        1. Hacking a one-off
        2. Prototyping
        3. Demonstrating how p00r yur skillz R

        ------
        We are the carpenters and bricklayers of the Information Age.

        Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

        I shouldn't have to say this, but any code, unless otherwise stated, is untested

      In other words, if it ain't a problem, don't fix it!

      A very dangerous statement, IMHO. It may be not a problem *YET*, but can turn into a problem later. I agree with you that he should know why the problem happens, but even if he can't he should correct it.

      This way he can produce a more "secure", "risk-free" code.

      Just my 2 cents.

      Regards,

      my ($author_nickname, $author_email) = ("DaWolf","erabbott\@terra.com.br") if ($author_name eq "Er Galvão Abbott");
Re: To initialise or not to initialise?
by melora (Scribe) on Jun 24, 2004 at 15:27 UTC
    I find quite often that my old C habits are actually preventing me from using features in Perl.

    For instance, I tend to initialize all variables when I declare them, because in C an uninitialized variable can, and usually does, contain garbage. However, this takes away the helpful "use of uninitialized variable" warning, so what worked for me in C really works *against* me in Perl. (Although the point about initializing to a default value is well taken)

    Another habit I have is that of declaring all global variables at the top of the file. This can lead to having to go to the top of a file to find out about a variable that is used down in the body of the code somewhere. Then again, as has been pointed out already, that can be due to a poor variable name. On the other hand, if I don't have it at the top of the file, I have to go find it. I think part of this dilemma, for me, goes back to the following:

    I still tend to use a lot of global variables, and I'm working at making variables just where I need them. (Keeps the "namespace" less cluttered? I'm still learning the lingo.) The classic example, for me, is the index variable of a for loop. No need, generally, to have it defined anywhere but within the loop, so why make it global? ("lexical" is the word I need?) And now that I've started learning about how to do OO programming in Perl, I can really start to "encapsulate" and avoid globals still more.

    So I guess I'm just a recovering C addict. Thanks to the supportive Perl Monastery community, though, I'm beginning to kick the habit.
      Are you really using global variables? You should be using lexical variables, declared with my, everyhere you can. For example, you can declare the loop variable inside the for statement.
      foreach my $item (@array) {

      I don't like the style of declaring lexical variables at the top of a function. I much prefer declaring the variable where it is first assigned. It must be a carryover from C where that is the only way to declare variables. But I can understand it.

Re: To initialise or not to initialise?
by skyknight (Hermit) on Jun 24, 2004 at 15:38 UTC

    Initialization is not simply a preference thing. Depending on the life time of your execution environment, not initializing things can get you into trouble, though I think you might be a little confused about when it matters.

    The only time that things are "reused" is in the case of things like mod_perl where the same handler may be used to serve multiple requests, and this is only in the case of global variables. If you have a variable that is scoped to a subroutine with "my", then it will always be initialized to undef when the subroutine is invoked, or to whatever value you specify.

    Where you can get into trouble is with subroutines that reference global variables, making the assumption that they are set to an undef state every time the subroutine is invoked. In the case of a one-shot Perl script, you can get away with this because the variable is in fact undef. With mod_perl, however, things might work as you expect the first time, but then crash on subsequent requests because the first invocation of the handler left stuff in the global variable, and the subsequent invocations of the handler assumed that the global was undef but it was not.

    For the most part, you should just avoid using global variables. However, as I mentioned in another post here, sometimes globals are legitimate, to a degree. Specifically, package wide variables make sense in many cases, and parallel the concept of "static member variables" in other languages. What you might declare in Java within a class as

    static int commonFoo = 0;

    would be declared in Perl as a package wide variable. A simple use for such a construct would be if you wanted to keep track of the number of objects of a certain type that had been allocated, then you might have your constructor for that class increment a package wide variable whenver it was invoked. As a more concrete example, in a RDMBS-OO mapper framework that I'm presently writing, I have the base class for objects maintain a hash array that holds the schemas for the database tables. There is no sense in each object holding its own copy of it. It's common to all instances of the class, and thus should live in a common place.

Re: To initialise or not to initialise?
by qq (Hermit) on Jun 24, 2004 at 21:12 UTC

    I with the camp that says don't initialize.

    That said, however, I'm constantly annoyed by the 'use of uninitialized ...' warning, usually when I'm interpolating a variable that I'm well aware might be undefined. It has to be the warning that I most often don't care about, and my code often grows constructs just to avoid it, which always looks ugly.

    qq

Re: To initialise or not to initialise?
by McMahon (Chaplain) on Jun 25, 2004 at 00:51 UTC
    I cut my teeth on COBOL and C, both of which have big issues with initialization.

    I'm still pretty much a Perl newbie, but since scoping is so easy and "use warnings" works so well, I haven't been motivated to do much initialization in Perl.

    On the other hand, I'm not managing 911 databases with Perl the way I did with COBOL and C.

    So if you need suspenders *and* a belt, initialize. Otherwise, Perl handles variable values in a pretty sane manner.