Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

A list assignment gotcha

by jcb (Vicar)
on Jul 30, 2020 at 02:01 UTC ( #11120043=note: print w/replies, xml ) Need Help??


in reply to Not understanding 2 sentences in perldoc

There is one other surprise in here that I once found the hard way: plain assignment will operate on lists, but modifying assignments (+= in the example that I recall) will not — if you try to increment a group of values, only the last item in each list is affected.

Replies are listed 'Best First'.
Re: A list assignment gotcha (updated)
by AnomalousMonk (Bishop) on Jul 30, 2020 at 03:38 UTC

    That's because the (scalar) operator of an op= imposes scalar context on the lists and so only the last element of each list is affected:

    c:\@Work\Perl\monks>perl -wMstrict -le "my ($x, $y, $z) = (30, 40, 50); ($x, $y, $z) += (3, 4, 5); print qq{$x, $y, $z}; " Useless use of a constant in void context at -e line 1. Useless use of a constant in void context at -e line 1. Useless use of private variable in void context at -e line 1. Useless use of private variable in void context at -e line 1. 30, 40, 55
    Raku can do these kinds of list operations; see Raku Programming/Meta Operators.

    Update: I'm not aware that you can do this with pure lists in Perl 5, but it can certainly be done with arrays:

    c:\@Work\Perl\monks>perl -wMstrict -le "my @ra = (30, 40, 50); my @rb = ( 3, 4, 5); ;; $ra[$_] += $rb[$_] for 0 .. $#ra; print qq{@ra}; " 33 44 55
    And via List::MoreUtils::pairwise():
    c:\@Work\Perl\monks>perl -wMstrict -le "use List::MoreUtils qw(pairwise); use vars qw($a $b); ;; my @ra = (30, 40, 50); my @rb = ( 3, 4, 5); ;; my @rc = pairwise { $a + $b } @ra, @rb; print qq{@rc}; " 33 44 55
    or
    c:\@Work\Perl\monks>perl -wMstrict -le "use List::MoreUtils qw(pairwise); use vars qw($a $b); ;; my @ra = (30, 40, 50); my @rb = ( 3, 4, 5); ;; pairwise { $a += $b } @ra, @rb; print qq{@ra}; " 33 44 55
    (The  use vars qw($a $b); statement quiets some warnings.)


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

      Exactly — they look analogous, but they are not. The List::MoreUtils tricks are interesting, but actually wrap a loop iterating over arrays instead of being a true "vectorized" modifying assignment. There is probably something in PDL for this if your program does that kind of processing, but for a simple case with a list of Perl scalars, you need to use multiple statements.

Re: A list assignment gotcha
by LanX (Cardinal) on Jul 30, 2020 at 11:37 UTC
    > plain assignment will operate on lists, but modifying assignments (+= in the example that I recall) will not

    If you really needed this, it could be done with a little syntactic sugar

    something like

    L($x,$y,$z) += L(1,2,3);

    the trick would be to let L() ( for "list" ) return an object with overload ed operators (in scalar context) performing the side-effect

    Tho I'm not sure if the RHS needs to be packed into an object too, but I assume += is imposing scalar context.

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

      A bit trickier than I originally thought. What I didn't expect was the need to use the :lvalue on both the listifier and constructor.
      #!/usr/bin/perl use warnings; use strict; use feature qw{ say }; { package L; use overload '+=' => sub { my ($self, $inc) = @_; $_ += shift @$inc for @$self; }; sub new :lvalue { bless $_[1], $_[0] } } sub L :lvalue { 'L'->new(\@_) } my ($x, $y, $z) = (10, 20, 30); L($x, $y, $z) += L(3, 2, 1); say "$x $y $z"; # 13 22 31
      You can use [3, 2, 1] on the RHS, as well.

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
        Hi

        > A bit trickier than I originally thought.

        I was about to update that one needs :lvalue and returning a tied scalar then.

        Surprised you made it without tie , my last use case must have been different than. :)

        update

        > You can use [3, 2, 1] on the RHS, as well.

        Nice! :)

        > on both the listifier and constructor.

        Genius!!! that's how you avoided using Tie::Scalar! :)

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

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://11120043]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (5)
As of 2021-01-20 12:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?