(jeffa) Re: Whether to use local()
by jeffa (Bishop) on Mar 15, 2002 at 18:45 UTC
|
"...why would you go to the trouble of using local if
you aren't trying to keep some private value ...
somewhere?"
Personally, i wouldn't. But the caveat depends on what kind
of program you are writing.
When i write utility scripts, avoiding global variables is
usually a waste of typing to me - i use them. Keep in mind
that i do have a CS degree and my professors would never allow us to use globals ever anywhere! I appreciated that, but now that i understand the rules, i can break them. >:)
Let's say that i am writing a larger program. Then i would
strongly consider OO. OO is good for eliminating globals,
because you instead have accessor methods (considering,
of course, that it is good OO).
Finally, local vs. my - in my limited experience with
local, i only use it to erase Perl's built-in variables,
like $/ for slurp mode (thanks again tye!):
my $slurp = do {local $/; <FH>};
All of my variables are declared with my. To be honest,
i am still missing the picture of when you need our.
Hope this helps :)
jeffa
L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
B--B--B--B--B--B--B--B--
H---H---H---H---H---H---
(the triplet paradiddle with high-hat)
| [reply] [d/l] |
|
# comment use strict in and out
# use strict;
package Foo;
our $global = 'global ';
$not_so_global = 'not so global';
package Bar;
print "Full package name: ", $Foo::global, $Foo::not_so_global, "\n";
print "No package name: ", $global, $not_so_global, "\n";
cheers
tachyon
s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print
| [reply] [d/l] |
|
Ahhhh, i am starting to see now:
- my declares a local variable which is not found in
a package's symbol table
- a local var does show up in the symbol table, but
if you use strict, then you have to fully qualify the
variable name (that is, prefix the package name)
- our handles the strict vs. non-fully qualified local
vars
perrin pointed me to CPAN and the Devel::Symdump
module. Here is another snippet to help explain:
#!/usr/bin/perl
#use strict;
use Devel::Symdump;
my $obj = Devel::Symdump->new('Foo');
print map {"$_\n"} $obj->scalars;
package Foo;
local $Foo::qualified;
local $unqualified;
our $our;
my $my;
Which (without use strict) produces this ouput :
Foo::qualified
Foo::our
Foo::unqualified
If strict is turned on, then $unqualified will cause a
compliation error. I think i get it now! :)
Thank you tachyon, perrin, and also rob_au for
pointing out What is it adding to my symbol table?.
jeffa
L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
B--B--B--B--B--B--B--B--
H---H---H---H---H---H---
(the triplet paradiddle with high-hat)
| [reply] [d/l] |
Re: Whether to use local()
by tachyon (Chancellor) on Mar 15, 2002 at 18:50 UTC
|
| [reply] |
Re: Whether to use local()
by PrakashK (Pilgrim) on Mar 15, 2002 at 19:38 UTC
|
My question is whether you should be concerned with scope if $new_mail needs to be shared between sub update_mail_list and sub read_mail_list etc.
One trick I sometimes use to share a variable among multiple subroutines, without making it a package variable is to enclose all of them in a block.
{
my $new_mail;
sub update_mail_list
{
# uses $new_mail
}
sub read_mail_list
{
# uses $new_mail
}
}
What do monks think about this style?
Thanks,
/prakash | [reply] [d/l] [select] |
|
I was wondering if someone was going to bring this up. To me, this is the best way to share a variable between two (or more) subroutines.
Just bear in mind, though, that you may receive puzzling errors regarding $new_mail being undefined, depending on where this code appears in the file, and how and when control gets passed to update_mail_list() or read_mail_list().
Best practices would suggest that rathing than enclosing the variable and the referring subs in bare { } braces, you should use a BEGIN { } block. This will ensure that $new_mail gets set up on the lexical pad before you get around to using it.
print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u'
| [reply] [d/l] [select] |
|
| [reply] |
|
That should only be a problem if you do that in an Apache::Registry script (and any similar beasts, if they
exist). If its in a module use'd by an A::R script (and maybe even in a non A::R handler?), it should be ok (if I'm not mistaken, and if you're careful).
| [reply] |
Re: Whether to use local()
by derby (Abbot) on Mar 15, 2002 at 19:14 UTC
|
jg,
OoooOOhh ... not only the messy mindfield of globals -vs- proper
scope but also the messy mindfield of where to define subroutines
(at the top before an implicit main, or at the bottom after the implicit
main). You should get lots of comments to this.
You should definetly minimize globals by using the my
operator. Check out "Private variables via my()" section in
perlsub. The thing to remember about using my is that
A "my" declares the listed variables to be local (lexically) to the enclosing block, file, or
"eval". So if you use my at the top of a package, all the methods/functions/subroutines
defined after can have access to that lexical.
Now the big question is "is that a big deal?" I disagree with a lot of my fellow
monks and feel it is not. demerphq has named this unintended globals
but that would be only if you accessed the lexical in your methods. My fellow
monks contend (and rightly so) that if you define your functions first and then your
lexicals, perl will complain. I feel that's too big a price to pay over readability (but
I've agreed to disagree about this point). My own opinion is to better know the code
you're writing/maintaining and ensure you don't utilize file scoped lexicals (can anyone
say code review).
Now when talking about packages, especially those which will be OO classes,
the norm is to usually hang all the objects attributes off a blessed hash - your need
for a package wide lexical is pretty small. Your need for true global variables is small also and should be kept to only those constructs which help with loading and
inheritance (@ISA, @EXPORT, @EXPORT_OK).
-derby | [reply] |
|
| [reply] |
Re: Whether to use local()
by shotgunefx (Parson) on Mar 15, 2002 at 18:31 UTC
|
local only works on global variables. (Anything in the symbol table.) my (lexicals) variables don't exist in the symbol table.
update
I realized I didn't really answer the question you where trying to ask. Declaring a my variable at the top of a file at worst is polluting one file. If you are writing the code and the files aren't huge, it's not all that hard to avoid shooting yourself in the foot with a little dilligence.
-Lee
"To be civilized is to deny one's nature." | [reply] |
|
local only works on global variables
my %foo;
$foo{bar} = " odd then?\n";
{
local $foo{bar} ="Isn't this";
print $foo{bar};
}
print $foo{bar};
:-P | [reply] [d/l] |
|
I know about local on hash elements and array elements but thought it would complicate the explanation for him. Just like I omitted PadWalker from the explanation of accessing lexicals. Point taken though. Was local on hash/array elements added as a hack for signal handlers? It seems the only real use that I've seen. Or is it used internally when you localize a package var in the symbol table seeing a package is in a sense a hash?
-Lee
"To be civilized is to deny one's nature."
| [reply] |
|
|
|
So you can't use local on vars you create if you are going to use strict? That seems strange to me. TIA jg _____________________________________________________ It's not my tree.
| [reply] [d/l] |
|
You can use both globals (package vars) and lexicals under use strict though globals need to be fully qualified ( $My::Mail::Server= "255.255.255.255";) Though globals are usually (not always) the wrong way to go.
The idea of lexicals are that they only exist in a scope thereby limiting access. What local does is let you temporarily save a value for a package var. It's a runtime trick and my is (mostly) a compile time trick.
The lowdown is package vars exist in packages and any can be accessed from any package. my vars exist in the scope they where declared in and cannot be accessed outside so you don't have to worry about other subs/modules etc clobbering your values.
You usually use local to save the value of $/ or $_ so you don't screw up code that calls your code. It has some other uses but that's one of the main one. There are probably a lot better explainations than mine and I'm sure if you do a search for lexical / package / global you will find a wealth of info here in the monestary.
UPDATE here is a great FAQ on "Coping with Scoping" by dominus. It's a far better explaination than mine.
-Lee
"To be civilized is to deny one's nature."
| [reply] |
|
|
|
Re: Whether to use local()
by erikharrison (Deacon) on Mar 15, 2002 at 18:50 UTC
|
local() gives a local value to a global variable. A local variable is visible to called subs but not calling subs. It seems to me that it would be difficult to use local to have class data. I think that this is one of those cases where a global is the correct solution to a problem. One shouldn't use globals to pass data to a subroutine - it's bad form, and it's confusing. However, since a class is a package in Perl, then a class global is the best way to store class data. Declaring the global with my makes it impossible for anyone else to accidentally change the variable outside of the lexical scope. I would also probably use a hash to make it very clear where the data is coming from:
package Class::Foo;
my %ClassData = ();
#methods here
Note however, that you have to be very careful if you are putting the class in the same file as the code which uses it - as a file (and NOT a package) delimits lexical scope, your class data might leak into the main program even if declared with my.
Cheers,
Erik | [reply] [d/l] |
Re: Whether to use local()
by dws (Chancellor) on Mar 15, 2002 at 18:53 UTC
|
My question is whether you should be concerned with scope if $new_mail needs to be shared between sub update_mail_list and sub read_mail_list etc.
I would be concerned, but I'd balance that concern against the size and complexity of the module, and whether there's a likelihood that the module would be extended or subclassed.
In your example, a global variable with package scope that is shared between two methods throws a major wrench into attempts to subclass either of the methods. Whether to use local depends on how the variable is shared.
| [reply] [d/l] |
Re: Whether to use local()
by dragonchild (Archbishop) on Mar 15, 2002 at 19:22 UTC
|
If $new_mail needs to be shared between two object methods, it makes sense to me to make $new_mail an attribute of the class you're in. (It's irrelevant if it's class data or instance data.)
Now, the question probably becomes "How do I make class data"? The best answer to that that I've found is to simply make a file-scoped lexical. You do have inheritance questions if you want children access to class data of their parents, but that's an implementation question. :-)
------ We are the carpenters and bricklayers of the Information Age. Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement. | [reply] |
Re: Whether to use local()
by YuckFoo (Abbot) on Mar 15, 2002 at 19:27 UTC
|
But more often than not, you just want to make your class
data a file-scoped lexical. To do so, simply put this at
the top of the file:
my $Census = 0;
Even though the scope of a my() normally expires when the
block in which it was declared is done (in this case the
whole file being required or used), Perl's deep binding of
lexical variables guarantees that the variable will not be
deallocated, remaining accessible to functions declared
within that scope. This doesn't work with global
variables given temporary values via local(), though.
YuckFoo
| [reply] |