http://qs1969.pair.com?node_id=11137524

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

I've come across this bit of code within an existing legacy script - not written by me

(my $pname,my $sname)=split / +/,$rname,2;

I'm wondering if it is functionally different to writing

my ($pname, $sname) = split / +/, $rname, 2;
I've tested the two against each other and they seem to behave exactly the same. But, is there some subtle difference my quick test has not uncovered?

Replies are listed 'Best First'.
Re: my within brackets
by jwkrahn (Abbot) on Oct 14, 2021 at 20:24 UTC

    It is useful in some cases. For instance if you do:

    my $y; ... my ( $x, $y, $z ) = split / +/, $rname;

    You will get a warning about an earlier declaration of $y. In this case you could do:

    my $y; ... ( my $x, $y, my $z ) = split / +/, $rname;
Re: my within brackets
by LanX (Saint) on Oct 14, 2021 at 18:07 UTC
    > But, is there some subtle difference my quick test has not uncovered?

    It's the same and it's explicitly documented to be so.

    See my VARLIST

    The rest is standard list assignment.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

      And, indeed, B::Deparse shows it to be so:

      Win8 Strawberry 5.8.9.5 (32) Thu 10/14/2021 17:49:15 C:\@Work\Perl\monks >perl -Mstrict -Mwarnings -MO=Deparse,-p my ($u, $v) = split /,/, 'U,V'; print "'$u' '$v' \n"; (my $w, my $x) = split /,/, 'W,X'; print "'$w' '$x' \n"; ^Z use warnings; use strict 'refs'; (my($u, $v) = split(/,/, 'U,V', 3)); print("'${u}' '${v}' \n"); (my($w, $x) = split(/,/, 'W,X', 3)); print("'${w}' '${x}' \n"); - syntax OK Win8 Strawberry 5.8.9.5 (32) Thu 10/14/2021 18:54:22 C:\@Work\Perl\monks >perl -Mstrict -Mwarnings my ($u, $v) = split /,/, 'U,V'; print "'$u' '$v' \n"; (my $w, my $x) = split /,/, 'W,X'; print "'$w' '$x' \n"; ^Z 'U' 'V' 'W' 'X'
      Same results with Perl version 5.30.3.1.


      Give a man a fish:  <%-{-{-{-<

        B::Deparse is occasionally wrong, it has to guess which code was optimized to what it finally sees.

        But the op-tree is more reliable

        D:\tmp\pm>perl -Mstrict -Mwarnings -MO=Concise my ($u, $v) = split /,/, 'U,V'; __END__ 9 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter v ->2 2 <;> nextstate(main 1 -:1) v:*,&,{,x*,x&,x$,$ ->3 8 <2> aassign[t4] vKS ->9 - <1> ex-list lK ->7 3 <0> pushmark s ->4 6 </> split(/","/)[t3] lK/IMPLIM ->7 4 <$> const[PV "U,V"] s ->5 5 <$> const[IV 3] s ->6 - <1> ex-list lKPRM* ->8 7 <0> padrange[$u:1,2; $v:1,2] RM/LVINTRO,range=2 ->8 - <0> padsv[$u:1,2] sRM*/LVINTRO ->- - <0> padsv[$v:1,2] sRM*/LVINTRO ->- - syntax OK D:\tmp\pm>perl -Mstrict -Mwarnings -MO=Concise (my $u, my $v) = split /,/, 'U,V'; __END__ 9 <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter v ->2 2 <;> nextstate(main 1 -:1) v:*,&,{,x*,x&,x$,$ ->3 8 <2> aassign[t4] vKS ->9 - <1> ex-list lK ->7 3 <0> pushmark s ->4 6 </> split(/","/)[t3] lK/IMPLIM ->7 4 <$> const[PV "U,V"] s ->5 5 <$> const[IV 3] s ->6 - <1> ex-list lKPRM* ->8 7 <0> padrange[$u:1,2; $v:1,2] RM/LVINTRO,range=2 ->8 - <0> padsv[$u:1,2] sRM*/LVINTRO ->- - <0> padsv[$v:1,2] sRM*/LVINTRO ->- - syntax OK D:\tmp\pm>

        Now, spot the difference! ;-)

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

      it's explicitly documented

      I had looked at the docs for my and didn't find it very explicit at all. It says "If more than one variable is listed, the list must be placed in parentheses" but makes no reference to having the my statement inside the parenthesis. Or am I missing something subtle in the documentation?

      This declaration seems unusual and I don't recall seeing it anywhere else which is why it stood out.

        this

        > "If more than one variable is listed, the list must be placed in parentheses"

        means:

        If VARLIST is

        $x,$y,$z

        you must write

        my ($x,$y,$z)

        The alternative

        my $x,$y,$z

        would only declare $x because of precedence, like

        (my $x),$y,$z

        Hence an alternative to what we want is

        my $x,my $y,my $z

        But since we need a list assignment on the LHS, we still need to put it all into parens

        (my $x,my $y,my $z) = split ...

        because this

        my $x,my $y,my $z = split ...

        would only assign to $z because of precedence°, like

        (my $x),(my $y),(my $z = split ...)

        HTH! :)

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

        Errata

        s/declare/assign to/ choroba++

        UPDATES

        °) Even worse, it would only be a scalar assignment to $z, i.e. the number of possible splits.

Re: my within brackets
by talexb (Chancellor) on Oct 14, 2021 at 19:50 UTC

    You've already got some answers, but I just wanted to throw my weight behind

    my ($pname, $sname) = split / +/, $rname, 2;
    as the usual and customary way to write that code. (I would use brackets with the split statement, but that's just my C experience speaking.)

    Alex / talexb / Toronto

    Thanks PJ. We owe you so much. Groklaw -- RIP -- 2003 to 2013.

      the usual and customary way to write that code

      Yes - I would always write it as my ($x, $y).
      It was precisely because it was not written that way that I noticed it as odd!

      WRT brackets in the split, I used to include them but have moved away from doing so as I feel it is easier to read without them. There was a time when I used brackets for virtually everything, including print statements! I do use them where they are not strictly necessary any time that precedence might be in less then obvious.

        Brackets help me visualize what the code is doing much faster. Looking at code without brackets just takes me longer to process. I write my code in a specific way, so I can read it as quickly and effortlessly as possible. :)

        Alex / talexb / Toronto

        Thanks PJ. We owe you so much. Groklaw -- RIP -- 2003 to 2013.

Re: my within brackets
by eyepopslikeamosquito (Archbishop) on Oct 14, 2021 at 23:35 UTC

    Bod, for future reference, note that B::Deparse is a handy way to see how the Perl parser interprets your code. Running:

    > cat bod-oh-my.pl (my $pname,my $sname)=split / +/,$rname,2; > perl -MO=Deparse bod-oh-my.pl my($pname, $sname) = split(/ +/, $rname, 2); bod-oh-my.pl syntax OK
    verifies that your razor-sharp Perl intuitions were spot on today.

    Update: In case you're interested, -MO=Deparse feels like an old friend to me, after using it time after time while testing and verifying Acme::EyeDrops and when playing golf. :)

      Thanks eyepopslikeamosquito - B::Deparse is something I have heard seen mentioned a few times in the Monastery. But, until now I haven't really thought it might help me. I shall add it to the (growing) list of things that I need to look into...

Re: my within brackets
by jo37 (Deacon) on Oct 14, 2021 at 20:19 UTC

    my may be used almost everywhere, as in the common idioms

    open my $fh, '<', $file;

    or

    while (defined (my $it = get_it())) { do_with_it($it); }

    Greetings,
    -jo

    $gryYup$d0ylprbpriprrYpkJl2xyl~rzg??P~5lp2hyl0p$

      It's more than that. my() even counts as (my) at the grammar level.

      Aside from their use of overriding precedence, their use in flow control statements, and their use in function prototypes and parameter lists, parens are syntactically significant in five places:

      $x = 4; # Scalar assignment operator (sassign) ($x) = 4; # List assignment operator (aassign) $x x 4 # String repetition operator (repeat) ($x) x 4 # Scalar repetition operator (repeat/DOLIST) \$x, $y # The referencing isn't distributed. \($x, $y) # The referencing is distributed. use Mod; # Calls import. use Mod (); # Doesn't call import. @a = ; # Illegal @a = (); # Stub operator

      my ($x, $y) is considered the same as (my $x, my $y) in all five of those circumstances.

      my ($x) = 4; # Same as: (my $x) = 4; my ($x) x 4 # Same as: (my $x) x 4 \my ($x, $y) # Same as: \(my $x, my $y) use Mod my(); # Same as: use Mod (); @a = my(); # Same as: @a = ();
Re: my within brackets
by perlfan (Vicar) on Oct 14, 2021 at 17:49 UTC
    I can't point to the docs, but it's parenthesis do not affect scope only precedence. There could be some exceptions, but that's generally how I think about it. E.g.,
    (my $line); # scoped outside of `while` block while ($line = <>) { }
    or
    while (my $line = <>) { # $line scoped only inside of `while` block }
    Treating my in a distributive way inside the parens shows your implicit understanding. I think. :-)

      It does more than affect precedence

      $ perl -M5.010 -e'sub f { 4,5,6 } say scalar( my $y = f )' 6 $ perl -M5.010 -e'sub f { 4,5,6 } say scalar( my ($y) = f )' 3

      See Re^2: my within brackets above