Re: where to declare a variable...
by dvergin (Monsignor) on Dec 09, 2001 at 08:28 UTC
|
Before the "if" blocks.
A common rule of thumb is that you want to
declare the variable in as narrow a scope as you can
and still be able to access it where you need to.
So you could try declaring the array inside the if blocks
for a very narrow scope. But then you would
discover that you were not able
to access it outside the scope of the if blocks --
which I presume you will want to do when you flesh out the
subroutine (otherwise why load the contents of the file
into the array in the first place).
------------------------------------------------------------
"Perl is a mess
and that's good because the
problem space is also a mess." - Larry Wall
| [reply] |
|
... you want to declare the variable in as narrow a scope as you can and still be able to access it where you need to.
++dvergin!
Of course, this assumes that the fragment presented was whittled down to some minimum amount needed to ask the question.
In other words, it's probably safe to presume that the if block would be followed by code which does something with the @entries array, such as return a reference to it or its contents, in which case perhaps something like this is more appropriate:
sub openFile {
my ($file1, $file2) = @_; # assume these are passed as parameters
my $fn = $file1 || $file2; # replaces the 'if' in original
open FH, $fn or die "$fn: $!";
my @entries = <FH>;
close FH;
# in list context, return the entire array, else (scalar context) a
+ref
return wantarray ? @entries : \@entries;
}
dmm
You can give a man a fish and feed him for a day ...
Or, you can teach him to fish and feed him for a lifetime
| [reply] [d/l] [select] |
|
Hi All,
A big thank you for taking the time to respond to my question on 'my'. This is definitely a place I'll keep coming back.
| [reply] |
Re (tilly) 1: where to declare a variable...
by tilly (Archbishop) on Dec 09, 2001 at 09:54 UTC
|
use Carp;
# Time passes...
# takes a filename, and returns the contents of
# the file as an array in array context, string in scalar.
sub read_file {
my $file = shift;
local *IN;
open(IN, "< $file") or confess("Cannot read '$file': $!");
return wantarray ? <IN> : join '', <IN>;
}
More accurate name. Better error reporting. Less code
duplication... | [reply] [d/l] |
Re: where to declare a variable...
by jryan (Vicar) on Dec 09, 2001 at 09:11 UTC
|
Dvergin is indeed correct when he says that you should declare @entries right before the if blocks; assuming, that is, that you are going to be using it outside of the if blocks. However, if the usage is going to be exclusive to inside of the blocks, you may want to consider declaring it twice, once for each block. Garbage collection is done at the end of the block the variable is declared in, so you will want your variables garbage collected as soon as possible if you are no longer using it. Here is an example:
my $entry = 1;
my $item;
while($entry)
{
$item = "foobar";
print $item;
$entry--;
}
In this example, $item is declared out of the loop, even though it is not used outside of the loop. Since it wasn't going to used outside of the loop, it should have been declared inside of the loop so that it was destroyed (and the memory it uses freed) when the block exits.
From looking at the context of your code, it appears that you might want to use @entries outside of the if statements, so you should follow dvergin's suggestion. Otherwise, always make sure that you declare your variables in the inner-most possible block that you can so that you don't unnecessarily tie up memory | [reply] [d/l] [select] |
|
In this example, $item ... wasn't going to used outside of the loop, it should have been declared inside of the loop so that it was destroyed (and the memory it uses freed) when the block exits.
You raise a valid point, but perhaps chose an inappropriate example. Particularly when a block is the body of a loop, you should weight the cost of creating and destroying a loop-scoped lexical variable against the need to keep the memory from being tied up. In this particular (obviously contrived) example, I might leave $item scoped outside the loop if I knew the loop would execute many times, just to avoid the create/destroy cost in terms of execution time and memory fragmentation (which itself might cost execution time later in the program, by slowing down subsequent allocations).
dmm
You can give a man a fish and feed him for a day ...
Or, you can teach him to fish and feed him for a lifetime
| [reply] [d/l] [select] |
|
In perl the lexical creation of my is a compile time action, The only run time effect is that it is asigned to or set to undef. local on the other hand is a run time directive and will have a speed penalty.
There is still a cost of entering and leaving lexical scopes in perl, but it is incured reguardless of variable declarations.
| [reply] |
Re: where to declare a variable...
by atcroft (Abbot) on Dec 09, 2001 at 12:47 UTC
|
Assuming there are reasons for the way you coded that routine (and you may wish to check for a better way to code it, although my guess is that is a striped-down version to focus on just the problem you present here), I think what I would do (although there are many more knowledgable here than I, and I hope they will correct me if I am in error) would be thus:
sub openFile {
my (@entries, $filename);
$filename = $file1 if ($file1);
$filename = $file2 if ($file2);
open(FH, $filename) or die($!);
@entries = <FH>;
close(FH)
# Other processing here
}
| [reply] [d/l] |
Re: where to declare a variable...
by Dylan (Monk) on Dec 10, 2001 at 13:58 UTC
|
Well, depends on what you want to do.
I quote, perldoc -f my:
A "my" declares the listed variables to be local (lexically) to the enclosing block, file, or "eval".
Let the code speak:
Run this code, study this code... :)
#!/usr/bin/perl
#Is you is, or is you ain't, my foobar?
#The dope on scope.
baz(); #call baz.
sub baz {
my $foobar="I feel Baz!\n";
print $foobar;
#$foobar is now lexically scoped for
#the whole subroutine block.
if (1) { #This is another block, it belongs to if.
my $foobar="I am the FooMan!\n";
print $foobar;
#$foobar is now lexically scoped
#for this if block;
}
print $foobar;
if ("I own several pairs of pants") {
#That ^^^^ is another if, and this is its block
my $foobar="I am the BarMan!\n";
print $foobar;
#$foobar is now lexically scoped for this if block;
}
print $foobar;
}
Now, what I would do for your little file opener is
sub openFile {
my @entries; #is now lexically scoped for the entire subroutine;
if ($file1) {
open FH, "$file1" or die $!;
@entries = <FH>;
close FH;
}
if ($file2) {
open FH, "$file2" or die $!;
@entries = <FH>; #Replace all the entries? what?
close FH;
}
}
Get it? Also, there are many flaws with the openFile code, but I digress Have fun! | [reply] [d/l] [select] |
|
Hi Dylan,
Thanks very much for explaining so clearly with that code of yours. I now understand 'my' and the meaning of scoping better.
cheers,
kiat
| [reply] |
Re: where to declare a variable...
by rje (Deacon) on Dec 10, 2001 at 20:38 UTC
|
Redeclaration
Bit bucket claims old data
Never to return
Only declare once
Vanquish data entropy;
Your comment is right
However,
There must be another option.
Could you do this?
open FH, $file1 or $file2 or die $!;
my @entries = <FH>;
close FH;
Rob
| [reply] [d/l] |
|
$fh = $file1 || $file2;
open FH, $fh or die $!;
etc
Sorry 'bout that.
Rob | [reply] [d/l] [select] |
A Simple Explanation of scoping
by tradez (Pilgrim) on Dec 11, 2001 at 03:38 UTC
|
Scoping is probably the most important part of good code. It helps allow for all aspects of good coding including polymorphism, inheritance, and even eventual OO'ification. A simple rule of thumb is that of the curly brakets. a "my"ed variable is only "visible" to the code in the same set of outermost curly brackets. Given this example:
sub main {
my $blah;
if ($blah =~/(\d+)\s{2}/) {
my $test = $1;
}
}
anything outside of the if {} will not see or be affected by the assignment of $test. but anything within sub main {} will be able to see $blah because it has been globally instantiated.
Hope that helps.
| [reply] [d/l] |