Re: Use of "my" after Perl v5.14
by tobyink (Canon) on Sep 20, 2012 at 22:36 UTC
|
my is not something new in Perl 5.14. It was introduced in Perl 5.0 almost 18 years ago, and is generally the recommended way of declaring variables. When you don't use my then you should have a damned good reason not to.
Perl traditionally allowed you to use variables without declaring them. The strict pragma (also introduced in Perl 5.0) can be employed to force the programmer to declare all their variables. Most Perl programmers use strict routinely. Perl 5.14 made the version declaration use v5.14 also automatically use strict mostly to save everyone some typing.
You have read wrong. my is not for "creating private variables in a subroutine"... or at least it's not exclusively for that. Try this example, which doesn't even define any subs:
#!/usr/bin/env perl
use v5.14;
{
my $var = "Hello world";
say $var;
}
say $var;
From this example, I hope you can see that lexical variables (those declared with my are not private to a sub; they are private to a lexical scope - that is, an area between curly braces. (Each whole Perl module/script is also a scope in itself.) Thus it's quite easy to declare a variable which can be seen outside a sub:
use v5.14;
my $global;
sub set {
$global = shift;
}
set("Hello world");
say $global;
The $global variable above is not fully global. It is available throughout the file, but other files cannot see it. (Say, in a situation where one module is trying to read a variable in another module.) This is often what you want.
Perl's true globals are package variables. These need to contain "::". For example:
$Foo::Bar::monkey = 'capuchin';
@Foo::Bar::monkies = qw( capuchin howler spider );
%Foo::Bar::monkies = (
capuchin => 1,
howler => 2,
spider => 3,
);
$::Hello = "World"; # is an alias for $main::Hello
Perl gives you a shortcut for package variables. If you're in package Foo::Bar, then you can use our $monkey to make $monkey act as an alias for $Foo::Bar::monkey.
{
package Foo::Bar;
our $monkey;
$monkey = 'capuchin';
}
{
package main;
use feature 'say';
say $monkey; # blank line (it's undefined)
say $Foo::Bar::monkey;
}
perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
| [reply] [d/l] [select] |
|
Thanks tobyink for such a elaborated and nice explanation..
| [reply] |
|
I suppose it's also worth mentioning that my and our have two other friends: local and state.
local sets a new, temporary value for a package variable, which expires at the end of the current scope, with the variable's original value being restored.
In this example, bar() sets $::hello temporarily to "Goodbye" and this new value is visible to foo(), but after bar() has finished running, the original value of "Hello" is restored again.
use v5.14;
sub foo
{
say $::hello;
}
sub bar
{
local $::hello = "Goodbye";
foo();
}
$::hello = "Hello";
bar();
say $::hello;
And state can be used to create a variable which keeps its state, not being re-initialised.
use v5.14;
sub counter {
state $count = 1;
say $count++;
}
counter();
counter();
counter();
counter();
perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
| [reply] [d/l] [select] |
|
|
|
Re: Use of "my" after Perl v5.14
by marinersk (Priest) on Sep 20, 2012 at 22:12 UTC
|
Consider this (notably, the difference between $localPrivateVarX and $localPersistentY):
#!/usr/bin/perl
use strict;
my $GlobalA = 1;
foreach my $notAGlobalB (qw /X Y Z/)
{
&displayDashedLine();
my $returnValueFromM = &subM($notAGlobalB);
print "Return: \$GlobalA = '$GlobalA', \$notAGlobalB = '$notAGlob
+alB', \$returnValueFromM = '$returnValueFromM'\n";
my $returnValueFromN = &subN($notAGlobalB);
print "Return: \$GlobalA = '$GlobalA', \$notAGlobalB = '$notAGlob
+alB', \$returnValueFromN = '$returnValueFromN'\n";
}
&displayDashedLine();
exit;
sub displayDashedLine
{
print "----------------------------------------\n";
}
sub subM
{
my ($parameterM1, @everythingElse) = @_;
my $localPrivateVarX;
if (!defined $localPrivateVarX)
{
$localPrivateVarX = 0;
}
$localPrivateVarX++;
print " SubM: \$GlobalA = '$GlobalA', \$parameterM1 = '$paramete
+rM1', \$localPrivateVarX = '$localPrivateVarX'\n";
return;
}
{
my $localPersistentY;
sub subN
{
my ($parameterN1, @everythingElse) = @_;
if (!defined $localPersistentY)
{
$localPersistentY = 0;
}
$localPersistentY++;
print " SubN: \$GlobalA = '$GlobalA', \$parameterN1 = '$para
+meterN1', \$localPersistentY = '$localPersistentY'\n";
return;
}
}
exit;
__END__
| [reply] [d/l] |
Re: Use of "my" after Perl v5.14
by marinersk (Priest) on Sep 20, 2012 at 22:37 UTC
|
I missed one of your questions, apologies:
Significance of "my": It has a measurably distinguished behavior distinct from "our". Most notably useful in Modules.
Pay attention to the value of $TRUE in the sample:
This is t2.pm:
#!/usr/bin/perl
use strict;
package t2;
# --------------------------------------------------------------------
+----------
# Constants (Operationally, if not technically)
# --------------------------------------------------------------------
+----------
our $RET_SUCCESS = 0;
our $RET_FAILURE = (-1);
our $RET_FATAL = (-2);
my $TRUE = 1;
my $FALSE = 0;
# --------------------------------------------------------------------
+----------
# version() - Returns the version number of this module
# --------------------------------------------------------------------
+----------
sub version
{
return sprintf "0.10a";
}
# --------------------------------------------------------------------
+----------
# Perl modules MUST return true
# --------------------------------------------------------------------
+----------
1;
__END__
This is t3.pl:
#!/usr/bin/perl
use strict;
use t2;
print "our: \$t2::RET_FAILURE = '$t2::RET_FAILURE'\n";
print " my: \$t2::TRUE = '$t2::TRUE'\n";
exit;
__END__
| [reply] [d/l] [select] |
|
And apologies accepted :)
| [reply] |
|
| [reply] |
|
I didn't get an error. But then I am not using v5.14.
| [reply] |
|
Re: Use of "my" after Perl v5.14
by AnomalousMonk (Archbishop) on Sep 21, 2012 at 04:42 UTC
|
What is difference between: -
while( my($index, $value) = each @rocks )
and
while((my $index,my $value) = each @rocks )
You can see what Perl thinks the difference is by using the O compiler backend interface to the B::Deparse module (invoked here with -p full parenthesization):
>perl -wMstrict -MO=Deparse,-p -le
"my @rocks = qw(a b c);
;;
while (my ($i, $v) = each @rocks) {
print qq{$i: '$v'};
}
;;
while ((my $i, my $v) = each @rocks) {
print qq{$i: '$v'};
}
"
BEGIN { $^W = 1; }
BEGIN { $/ = "\n"; $\ = "\n"; }
use strict 'refs';
(my(@rocks) = ('a', 'b', 'c'));
while ((my($i, $v) = each(@rocks))) {
do {
print("${i}: '${v}'")
};
}
while ((my($i, $v) = each(@rocks))) {
do {
print("${i}: '${v}'")
};
}
-e syntax OK
Apparently, Perl doesn't think there is any difference at all. (Same results under Strawberries 5.12.3.0 and 5.14.2.1.)
See also Basic debugging checklist.
| [reply] [d/l] [select] |
|
| [reply] |
|
| [reply] [d/l] [select] |
Re: Use of "my" after Perl v5.14
by Rohit Jain (Sexton) on Sep 20, 2012 at 23:09 UTC
|
Ok.. Now that I have read something new, my doubts are clear..
Actually, its not about private or global.. Its about lexical scope of the variable.. when we declare a variable with "my", its lexical scope is the nearest outer block of that variable.. So, a lexical scope can at max be a file..
After Perl 5.10 we can use "state" to define a state variable within subroutine to maintain the state of the variables between different calls.. By this we don't have to use global variables in the subroutine.. And also, we don't have to declare it through "my" which otherwise would have got new value for each call..
E.g: -
use 5.010;
sub marine {
state $n = 0; # private, persistent variable $n
$n += 1;
print "Hello, sailor number $n!\n";
}
Had the declaration been "my $n = 0", then for every subroutine call it would start with 0..
Thanks everyone for your reply.. :)
| [reply] [d/l] |
|
Had the declaration been "my $n = 0", then for every subroutine call it would start with 0...
Depending on where "my $n = 0" was placed and how. Using "my $n = 0" outside the subrourtine, placed in a block like so:
for (1..5){marine()};
{
my $n=0; # private, persistent variable $n
sub marine {
$n += 1;
print "Hello, sailor number $n!\n";
}
}
will work exactly, like using:
use 5.010;
for (1..5){marine()};
sub marine {
state $n = 0; # private, persistent variable $n
$n += 1;
print "Hello, sailor number $n!\n";
}
If you tell me, I'll forget.
If you show me, I'll remember.
if you involve me, I'll understand.
--- Author unknown to me
| [reply] [d/l] [select] |
|
| [reply] [d/l] |
Re: Use of "my" after Perl v5.14
by Rohit Jain (Sexton) on Sep 20, 2012 at 22:31 UTC
|
Ok.. so I was just getting confused with local variable as private variables.. They both are same.. just the name used at a wrong place.. Because private and public should come at a place where you start talking OOP.. It is just global and local variables in this case.. am I right??
| [reply] |
|
Actually, I will confess to an atypical ignorance on the difference between "local" and "private" and will defer to the real Perl experts on this forum to answer your very appropriate question.
The point I was trying to make is that to make a variable which is global to a source file, you put the "my" outside all subroutine defintions, and that you could make a relatively localized variable which persists its value through the use of braces in what I believe is called "lexical scoping".
Regardless of the terms, the sample demonstrates a number of functionally distinct scope limits for your variables.
We should know the professional terms, but I, frankly, don't.
| [reply] |