Re: using strict and functions
by Desdinova (Friar) on Jan 17, 2002 at 22:04 UTC
|
use vars qw($var1 @array2};
That will give you the effect of a global var (actually a package var.) Without strict complaining too much. There is a great discussion of this here
Another option would be to pass the functions a reference to the variable. See perlref for details on using references. In my opinion this is a better way because it makes your functions more usable in other programs.
Also if they are small vars you can just pass them to the function in your call. If it is a huge list you will get better performance with the reference though.
UPDATE: Removed the comma per the comment below btw- you are bieng no more 'picky' than perl itself <g> | [reply] [d/l] |
|
| [reply] [d/l] [select] |
Re: using strict and functions
by runrig (Abbot) on Jan 17, 2002 at 22:01 UTC
|
You can localize them to the functions
(the 'BEGIN' is so that any initializations
to the variables get
done no matter where you place these functions
in the program):
BEGIN {
my ($var1, $var2) = ("this", "that");
sub sub1 {
# use $var1, $var2
}
sub sub2 {
# use $var1, $var2
}
}
Update: It's hard to tell what you really want or need from
your description, so its a good thing there are lots of
good answers here..
| [reply] [d/l] |
|
This turns sub1 and sub2 into closures (see 'What's a closure?'). While it is not always necessary to use BEGIN blocks, without them (i.e. normal blocks), declaration order becomes significant.
Update: A trick I use occasionally is to declare a set of lexical variables in a BEGIN block along with access functions. Within the program, only the access functions are visible.
BEGIN {
my ($var1, $var2, $var3);
my @array1;
my %hash1;
sub var1 { $var1 = $_[0] if @_; $var1 }
sub var2 { $var2 = $_[0] if @_; $var2 }
sub var3 { $var3 = $_[0] if @_; $var3 }
# for arrays and hashes, call in scalar context and
# dereference to manipulate contents
sub array1 { wantarray ? @array1 : \@array1 }
sub hash1 { wantarray ? %hash1 : \%hash1 }
}
Of course, rather than hand code access functions for every variable, I typically define a hash containing my variables as keys, and an AUTOLOAD to define access functions dynamically on first use.
dmm
If you GIVE a man a fish you feed him for a day
But, TEACH him to fish and you feed him for a lifetime
| [reply] [d/l] [select] |
Re: using strict and functions
by talexb (Chancellor) on Jan 17, 2002 at 22:16 UTC
|
In addition to the excellent technical answers you're getting, let me also add a style comment.
Only declare variables when you need them. If you need a loop variable, don't declare it away at the beginning of the routine or (horrors!) at the top of the file. Just declare it where you're gonna need it, like this:
for ( my $Index = 0; $Index < 5; $Index++ )
{
... # code here that uses $Index
}
If you're going to need two variables somewhere in the middle of a block of code, declare them there. In some languages you do have to declare all variables at the beginning (Pascal, and I think BASIC) .. but C and Perl give you more flexibility. So you could write
{ # Start black of code
..
..
{ # Start another block of code
my ( $Index, $NodeNumber );
..
..
}
..
..
}
This just declares the two variables where you need them. As soon as the scope (the code between the braces) ends, the variables disappear. Very neat, very clean.
--t. alex
"Of course, you realize that this means war." -- Bugs Bunny.
| [reply] [d/l] [select] |
|
| [reply] |
|
Hmm...I think you meant to say C++ here. C doesn't give you that kind of flexibility; however, C++ does.
#include <stdio.h>
int main ( int iArgC, char * apsqArgV[] )
{
printf ( "Hello, world! This is cygwqin speaking.\n" );
{
char szMsg[] = "Not so!";
printf ( "Now inside scope, msg is %s.\n", szMsg );
}
return ( 0 ); // Success is zero in Windows.
}
This is the kind of scope that I was talking about. The char array szMsg is declared at the start of the scope; this code compiles and runs correctly under CygWin (Win98).
You may have been talking about the following:
void FooBar ( void )
{
int iBeer, iVodka;
float fCredit = 20.0;
.. /* Code here */
iBeer++;
fCredit -= 2.50;
.. /* More code */
char *apszVarious[]; /* ILLEGAL in C */
}
I will grant that this kind of variable declaration is valid in Perl but not valid in C.
--t. alex
"Of course, you realize that this means war." -- Bugs Bunny.
| [reply] [d/l] [select] |
|
|
One point here ... Your use of the loop construct of for (;;) is very C-stylish and possibly not the best way to perform a simple forward iteration as your suggest. A more straight-forward way would be to make use of the range operator. eg.
for (0..5) {
# stuff goes here
}
If you require lexical scoping of the iteration variable, you can do so with the variable name and the my keyword.
This syntax and the range operator are discussed in perlsyn and perlop respectively.
perl -e 's&&rob@cowsnet.com.au&&&split/[@.]/&&s&.com.&_&&&print'
| [reply] [d/l] [select] |
Re: using strict and functions
by mirod (Canon) on Jan 17, 2002 at 22:40 UTC
|
You can also declare a global hash (or array, but a hash is more convenient) containing the variables and pass it around as a parameter to the functions:
my $state= { var1 => "value1", var2 => "value2"};
sub f1
{ my( $other_param, $state)= @_;
$state->{var2}= "new_value2";
# ...
}
...
This way you group the variables together cleanly and
you can pass them to the functions without clobbering
your parameter lists.
Of course if you want to get OO brownie-points you can also make $state an full-blown object, but that would be an other story node... | [reply] [d/l] |
Re: using strict and functions
by strat (Canon) on Jan 17, 2002 at 22:04 UTC
|
There are some variables that can't be used with my, e.g. $" or the like. In this case, you have to use local.
sub MyFunc {
local $" = shift;
my @list = @_;
print "@list\n";
} # MyFunc
But always try to use my before using local.
Best regards,
perl -e "print a|r,p|d=>b|p=>chr 3**2 .7=>t and t" | [reply] [d/l] [select] |
Re (tilly) 1: using strict and functions
by tilly (Archbishop) on Jan 18, 2002 at 22:49 UTC
|
This looks to me to be an example of believing that a fundamental issue can be fixed by renaming what you are doing.
It doesn't work like that.
The effect that you are trying to achieve is that of a global. If you succeed in achieving that effect, you will have all of the fundamental design advantages and disadvantages that globals have. (They do have both.) The mechanism that you use to achieve the effect has no relevance beyond the fact that you are imposing overhead and obscuring what you are doing.
This is why I recommend that people not just understand that something is bad, but also understand why it is bad. We tend to complain of "cargo cult" code where people borrow code by rote without understanding. But the flip side of the same coin is no better in the end, accepting that certain labels are bad without understanding why.
Therefore, unless you want a specific subtly different effect than what globals give, I would be honest about it and just declare a global with vars. Oh, every alternative will have small advantages and disadvantages over this. For instance using a single global hash gives you only "one" global - but you impose overhead and lose typo checking.
For more on the issues with globals, and how changing the label does (not) address them, see Pass by reference vs globals. | [reply] |