http://qs1969.pair.com?node_id=591922

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

Hello Monks,

I have been searching about for how to declare a variable, ranging from SuperSearch to just using the search function, and have not found an article or node that may satisfy my curiosity.

What I wish to know was that I came across another post on this node of Seekers of Perl Wisdom that looked like this:

#!/usr/bin/perl -w use strict; use warnings; CheckAllPairs(); CheckAllPairs(); sub CheckAllPairs{ my $abs_time_res=50; my $max_peak_time=2050; my $subj_num; my $region; my $region1; my $region2; my $time; my $peaks; my @act_list1; my @act_list2; my $i; my $j; my $key; my $delta; my %map; my $start_A; my $end_A; my $start_B; my $end_B; my @region_list = (1..38); my @main_subjects_list = (1..38);

I was wondering if this is a good example of declaring variables at the beginning of a script, which, in this case, also uses the recommended USE STRICT call at the beginning of this example snippet?

As always, thank you, and I think when all is said and done, I may be creating a FOR BEGINNERS section if I'm not careful.

Replies are listed 'Best First'.
Re: Declaring a Variable [for BEGINNERS]
by merlyn (Sage) on Dec 27, 2006 at 21:18 UTC
    It's been demonstrated repeatedly that you really can't deal with more than 7 (plus or minus 2) things in your active brain at a time. (Unless you're a chess grandmaster, but that's a different story.)

    Given that, you have about 25 things "in play" right after "my @main_subjects". There's really no point in that.

    Instead, as others have said, introduce things as you need them (to give them a meaningful context), but more importantly, also figure out ways to reduce the scope of items, to take them "out of play" as soon as possible.

    For example, presuming you needed that $i just for a loop, declare it as part of the loop. Or if $region is used only for a few steps, either put those steps into a subroutine (so the inputs and outputs are clearly defined), or at least put it into a block:

    { my $region = 1; ... }

    Also, variables with names like "@act_list1" and "$region2" hint to me that they really ought to be part of an array. Almost certainly, you're going to get to see code that does exactly the same thing to @act_list1 and @act_list2. Naming them as separate variables means you'll have to copy some of your code. If they were part of an array, you could just iterate over the array.

    And finally, there's a school of thought that a variable should be "born meaningful". Having a bunch of declarations at the front means they'll have to have some temporary dummy value in them until the time that their real initial value is computed. What's the point in that?

    Just a few tips there.

Re: Declaring a Variable [for BEGINNERS]
by Old_Gray_Bear (Bishop) on Dec 27, 2006 at 20:27 UTC
    That is one way to do it, but....

    My personal preference is to 'declare' the variable in the scope where it will be used, rather than having a huge clump-o-names at the start of the code. There are at least two reasons for this:

    1. I don't like leaving variables exposed to the vagaries of later maintenance coders. (Coders, please note, as opposed to programmers.) There is a tendency for Coders to look for an 'unused' variable when they are making enhancements, and grabbing one from the clump at the front is just so tempting. ("Hey, I saved allocating another variable! I'm being Efficient and Reusing code and all that Best Practice Stuff....")
    2. A clump-o-variables is a strong indication of maintenance headaches to come. That variable you saved in (1), well you changed its value didn't you? And you didn't save the old value so you could restore it after you were done, did you? Your new Code Works, but you have introduced (potentially) bugs in the Old Code that depended on the value in that Global Variable that you just stomped on....
    3. A clump of declarations makes it harder to figure out where the logic starts, unless you are very very clear with your comments. How many times have I run across  my $var;$var=fps(1.234);$mumble=tilde($var);my next_vat; buried in the middle of a bunch of declarations?
    4. A Clump-O-Variables at the start of your code means you have a Clump-O-Global-Variables. Global variables have 'action at a distance' properties.
    As for
    use strict; # Note: all in lower case use warnings;
    Don't start coding without it. (And don't start me on that rant again!)

    The clump-o-variables (and it's sibling the clump-o-subroutines) is often the hallmark of someone who has written a lot of C or Shell, where you really had to declare before use. The Perl compiler is a little brighter than that. Constructing your code so that it assists in understanding the logic-flow is a good thing. Clumps of things that impede the understanding should be avoided.

    That said, the clump-o-something is a valid way to write Code. It's not a style I like, or encourage. But it is a valid style, if it fits your way of seeing the Code. Just bear in mind, if I am the next programmer to do maintenance on this, I may drink an awful lot of coffee before I understand how my fix should fit in. (And a Wired Old Bear is not exactly a pretty sight...)

    Update -- Fixed broken link; thanks (ysth).

    ----
    I Go Back to Sleep, Now.

    OGB

        The clump-o-variables (and it's sibling the clump-o-subroutines) is often the hallmark of someone who has written a lot of C or Shell, where you really had to declare before use. The Perl compiler is a little brighter than that. Constructing your code so that it assists in understanding the logic-flow is a good thing. Clumps of things that impede the understanding should be avoided.

      If I can come to the defense of C, both languages permit you to declare locally scoped variables at the start of a block. Only in Perl can you declare variables mid-block, although I haven't tested that recently.

      Alex / talexb / Toronto

      "Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

Re: Declaring a Variable [for BEGINNERS]
by gaal (Parson) on Dec 27, 2006 at 19:44 UTC
    This example does not declare variables in the beginning of the script: that is, these variables are only visible inside the scope of the sub CheckAllPairs. This is called "lexical" scoping, and extends from a "my" declaration to the end of the scope of the my. Perl also has global variables, which you usually use the "our" declarator to introduce, but as a rule of thumb lexicals are better for most purposes.

    Using strict is almost always a good idea, yes. Having so many variables like in that example looks like a lot, but maybe it's warranted by what the code is doing. If you want to declare several lexicals all at once rather than on separate lines, you can do it the following way, but it's mostly a stylistic thing:

    my ($subj_num, $region, $region1, $region2, $time); # put as many as y +ou like here my ($abs_time, $max_peak_time) = (50, 2050) # you can initiali +ze multiple vars like this.
Re: Declaring a Variable [for BEGINNERS]
by ikegami (Patriarch) on Dec 27, 2006 at 21:17 UTC

    While one doesn't need to limit the existance of a variable to the minimal scope in which it is used, the post to which you refere was lax with at least its loop counter variables. There's value in declaring all the variables in one spot (to document them easily), but there's no rarely any reason to access loop counters outside of a loop (and there's probably a better way when there is a reason).

    my $region1; my $region2; . . . foreach $region1 (@region_list) { foreach $region2 (@region_list) { ... } }

    would surely be better as

    foreach my $region1 (@region_list) { foreach my $region2 (@region_list) { ... } }

    In fact, declaring the variables at the top forced the author to come up with new variable names. Instead of having two loops iterating using $region, he had to create $region1.

    my $region; my $region1; . . . foreach $region (@region_list) { ... } . . . foreach $region1 (@region_list) { ... }

    would surely be better as

    foreach my $region (@region_list) { ... } . . . foreach my $region (@region_list) { ... }

    Unrelated, the author could have used true constants for the constants, and used an array to store the times. This would have reduced the number of variables and improved readability.

Re: Declaring a Variable [for BEGINNERS]
by scooper (Novice) on Dec 28, 2006 at 04:26 UTC
    Always put the for loop iterator variables as 'my' inside the for loop.
    foreach my $region (@regions) { # something happening in the loop }
    If you write
    my $region foreach $region (@regions) { # something happening in the loop }
    Perl silently declares a new lexical variable (also named $region) as the iterator variable. The new $region is scoped to the loop block and hides any variable $region from the outer scope. By explicitly putting the my in the foreach, you're reminding yourself of this behaviour. You're avoiding the misconception that the last value of $region will be available after the for loop (it won't, however you try to scope it). If you want that information you have to save it to an outside variable inside the loop
    my $latest_region; foreach my $region (@regions) { $latest_region = $region; # something happening in the loop last if (some condition); } print "last region considered was $latest_region\n";
    Most of this information lifted from "Non-Lexical Loop Iterators", 'Always declare a for loop iterator variable with my', in "Perl Best Practices", by Damian Conway
Re: Declaring a Variable [for BEGINNERS]
by philcrow (Priest) on Dec 27, 2006 at 20:24 UTC
    Most people would declare at least some of the varaibles closer to where they are used, saving initial declarations for things used widely throughout the routine.

    Phil

Re: Declaring a Variable [for BEGINNERS]
by Anonymous Monk on Dec 27, 2006 at 21:08 UTC
    Hi,
    Welcome to Perl!
    Delaring variables can be done at the beginning of your program/code or at the point where you being to use those variables in the code.
    For example,you may declare varaibles at the beginning of your code as in -
    #!/usr/bin/perl use strict; use warnings; my $variable1; my $variable2; ... ... ### Rest of the code follows from below ... ... ### End of the code
    Also, if you are declaring variables close to the point where you begin to actually use them, you may do something as below:
    #!/usr/bin/perl use strict; use warnings; .... .... ... for (my $variable1=0; $variable1 <= $#someArray; $variable++) { ### Do something here ... ... } ... ### Rest of the code here ...

    Best Regards,
    garbage777
Re: Declaring a Variable [for BEGINNERS]
by brusimm (Pilgrim) on Jan 02, 2007 at 16:17 UTC
    Thank you everyone for your insights. There are perspectives here that I had not thought of, or encountered yet, and I appreciate the time & text on the matter & everyone's help.