Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

... for (@_) x= 2;

by rsFalse (Friar)
on Dec 28, 2015 at 20:38 UTC ( #1151286=perlquestion: print w/replies, xml ) Need Help??

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

Hello,

I wrote codes, which seems for me equivalent, but their behaviour differ. Any ideas, why they differ? ...I can't catch.
#!/usr/bin/perl use warnings; use strict; $\ = $/; @_ = ('a' .. 'b'); print for (@_) x= 2;
OUTPUT:
Can't modify array dereference in repeat (x) ... Execution of arrX2.pl aborted due to compilation errors.
#!/usr/bin/perl use warnings; use strict; $\ = $/; print for (@_ = ('a' .. 'b')) x= 2;
OUTPUT:
2 2
UPD. Added:
#!/usr/bin/perl use warnings; use strict; $\ = $/; (@_ = ('a' .. 'b')) x= 2; print for @_;
OUTPUT:
a b
P.S. parentheses around 'a' .. 'b' are redundant.

Replies are listed 'Best First'.
Re: ... for (@_) x= 2;
by 1nickt (Abbot) on Dec 28, 2015 at 21:20 UTC

    x= , the repetition assignment operator, only works on scalars.

    So you can do:

    my $str = 'ab'; $str x= 2; print $str; # 'abab'

    You don't say what you want as output, but maybe you are looking for:
    #!/usr/bin/perl use warnings; use strict; $\ = $/; @_ = ( 'a' .. 'b' ) x 2; print for @_;
    Output:
    a b a b
    edit: show example of repetition assignment on a scalar
    The way forward always starts with a minimal test.
      Yes, firstly, I wanted so for an output, but later I found that behaviours are interesting with using 'x=' operator :) . I experimented if I can multiply the array in 'for' sentence with using 'x='.

        Just in case this is not obvious, map tends to produce a more consistent solution in these situations:

        perl -le'print map $_ x=2, ("a" .. "f")'

        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)
        
Re: ... for (@_) x= 2;
by GrandFather (Sage) on Dec 28, 2015 at 21:59 UTC

    I suspect the key is that x= only operates on scalars. So (@_ = ('a' .. 'b')) is in scalar context and becomes the scalar value 2 which x then make two of.

    Premature optimization is the root of all job security
      ok but ...

      > which x then make two of.

      .. it's not an x but a combined assignment x= and it's tricky to see what exactly the target of this assignment is.

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Je suis Charlie!

Re: ... for (@_) x= 2; (scalar assignment)
by LanX (Archbishop) on Dec 28, 2015 at 23:23 UTC
    I had problems to understand what your goal is, this code already looks broken.

    It's true that x has a double nature (repeat string vs repeat list) like .. depending on context (flip flop vs range)

    But "combined assignments" like += only allow scalars on the LHS...

    See perlop

    > These combined assignment operators can only operate on scalars, whereas the ordinary assignment operator can assign to arrays, hashes, lists and even references.

    update

    Besides you don't need any assignment

    print for @_ x 2 should already work perfectly.

    update

    correction print for (@_) x 2 should already work perfectly.

    DB<100> @_=1..3 => (1, 2, 3) DB<101> print for @_ x 2 => "" 33 DB<102> print for (@_) x 2 => "" 123123

    from perlop

    > In list context, if the left operand is enclosed in parentheses or is a list formed by qw/STRING/, it repeats the list.

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

      I supposed that three of my codes looks equivalently (for me), so and output should be the same - e.g. warning + compilation error.
        the list assignment returns the length of the list in scalar context, so
        DB<114> $l = ( @a = qw/a b/ ) => 2

        So it's not the same code!

        The difference between your code and my example is that there is no explicit variable (like $l) used here, but somehow it's still possible to change it.

        Maybe it's a side effect of for ? I dunno.

        I'd prefer a Can't modify warning here too!

        But it's still a very peculiar construction, so I'm not surprised if this edge case wasn't covered.

        HTH!

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)
        Je suis Charlie!

        update

        More insights:

        ... it's not the temporary scalar which is modified but the resulting list in brackets

        DB<121> print "$_\n" for ($a=666) x= 2 666 666 => "" DB<122> $a => 666

        According to the already cited documentation of "combined assignments" this shouldn't be possible, b/c its a list operation.

      LanX cited: "> In list context, if the left operand is enclosed in parentheses or is a list formed by qw/STRING/, it repeats the list."

      Now I tried to write some lines with 'qw' and found next interesting situation, which I can't understand:
      #!/usr/bin/perl use warnings; use strict; $\ = $/; $, = '+'; print qw/a b/ x 2; print scalar(qw/a b/ x 2); print for (qw/a b/ x 2) x 2; print for qw/a b/ x 2 x 2;
      OUTPUTS:
      a+b+a+b
      bb
      a b a b a b a b
      bbbb
      The strange for me is the output of second 'print' (of course so does 4th too): it prints "bb" instead of supposed "b". I don't catch that, because print scalar('a','b','a','b'); would print "b".
        the documentation says that x can only act like a list repeater in list context.

        > > In list context, if the left operand is enclosed in parentheses or is a list formed by qw/STRING/, it repeats the list.

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)
        Je suis Charlie!

Re: ... for (@_) x= 2;
by Anonymous Monk on Dec 28, 2015 at 23:48 UTC
    simpler:
    $ perl -E '$x = "foo"; say for $x x= 2'
    that compiles to (only relevant part):
    BINOP (0x189a938) repeat [1] UNOP (0x189a9c0) null [15] SVOP (0x189aa00) gvsv GV (0x197dac8) *x SVOP (0x189a980) const IV (0x197dae0) 2
    while
    $ perl -E '$x = "foo"; say for ($x) x= 2'
    is actually
    BINOP (0xecd938) repeat [1] UNOP (0xecd8f0) null [158] OP (0xecd8b8) pushmark UNOP (0xecd9c0) null [15] SVOP (0xecda00) gvsv GV (0xfb0ac8) *x SVOP (0xecd980) const IV (0xfb0ae0) 2
    and
    $ perl -E '@x = (@_ = qw( a b )) x= 2'
    is
    BINOP (0x14b79b8) repeat [4] UNOP (0x14b7970) null [158] OP (0x14b7938) pushmark BINOP (0x14b7a40) aassign [3] UNOP (0x14b7b40) null [158] OP (0x14b7b08) pushmark SVOP (0x13ffc38) const PV (0x159ab28) "a" SVOP (0x13ffbe0) const PV (0x159ab70) "b" UNOP (0x14b7ac0) null [158] OP (0x14b7a88) pushmark UNOP (0x13ffc78) rv2av [2] SVOP (0x13ffcb8) gv GV (0x13de0d0) *_ SVOP (0x14b7a00) const IV (0x159ab58) 2
    So pretty much like GrandFather said. Hopefully that answers your question. I don't think it's documented anywhere; see toke.c and perly.y if you want more details. Certainly this behaviour is subject to change without notice.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (4)
As of 2019-06-24 23:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Is there a future for codeless software?



    Results (100 votes). Check out past polls.

    Notices?