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.
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.
| [reply] [Watch: Dir/Any] [d/l] |
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:
- 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....")
- 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....
- 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?
- 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
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
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
| [reply] [Watch: Dir/Any] |
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.
| [reply] [Watch: Dir/Any] [d/l] |
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.
| [reply] [Watch: Dir/Any] [d/l] [select] |
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 | [reply] [Watch: Dir/Any] [d/l] [select] |
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 | [reply] [Watch: Dir/Any] |
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 | [reply] [Watch: Dir/Any] [d/l] [select] |
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. | [reply] [Watch: Dir/Any] |
|
|