http://www.perlmonks.org?node_id=994764

Rohit Jain has asked for the wisdom of the Perl Monks concerning the following question:

What is difference between: -

while( my($index, $value) = each @rocks )

and

while((my $index,my $value) = each @rocks )

I have read that "my" is used for creating private variables in a subroutine.

But if we use "use v5.14" then using "my" is compulsory whenever we are creating variable for the first time. Then in that case, if a variable is declared for the first time in a subroutine, it has to be private always(forcefully due to v5.14)

So how do we declare a non-private variable(global variable) in Subroutine.. At first it didn't make sense to me to have global variables in a subroutine.. But it is a topic in a book..

So is there any major signifance of "my" in Perl

And Yes.. I am Overwhelmed by how length of an array is easily replaced in a scalar context.. No function needed at all.. Wow!! :) :)

Replies are listed 'Best First'.
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'
      Thanks tobyink for such a elaborated and nice explanation..

        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'
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__
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__
      And apologies accepted :)

      I think $TRUE variable will not be visible in second file from t2 package.. Because it is declared to be private in that package.. Will it show compiler error??

        I didn't get an error. But then I am not using v5.14.
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.

      Frankly, I didn't understand few segments of that code.. (Especially that BEGIN..But will come over again when I gain some more experience coding Perl..

      Thank You :)
        I didn't understand few segments of that code.. (Especially that BEGIN..

        Those two blocks are inserted by the compiler in response to the  -w and  -l command line switches, respectively. (See perlrun for info on all switches.) Try deparsing the command line invocation with and without the switches and see the effect!

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.. :)

      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

      Almost exactly right! A state variable has a lexical scope of visibility, but the value persists across control flow leaving that scope.

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??

      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.