Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

u+ fails to force scalar context to empty list assignment: +( () = ... )

by rsFalse (Hermit)
on Mar 11, 2019 at 17:05 UTC ( #1231129=perlquestion: print w/replies, xml ) Need Help??

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

Hello.

Today I've found that unary plus (u+) doesn't force scalar context to empty list assignment. Isn't this bug or DWIdon'tM?
#!/usr/bin/perl -wl use strict; $_ = '--;--;----;'; print +( () = /;/g );
OUTPUT: an empty line.

Overcome with same idea:
print - -( () = /;/g );
OUTPUT: 3

Verbose overcome :)
print scalar( () = /;/g ); # or "secret op": print ~~( () = /;/g );
OUTPUT: 3

Interesting (I expected a compilation error here, similar as with number predecrement, e.g. --5):
print --( () = /;/g );
OUTPUT: 2

Replies are listed 'Best First'.
Re: u+ fails to force scalar context to empty list assignment: +( () = ... )
by tybalt89 (Parson) on Mar 11, 2019 at 17:18 UTC

    From perlop

    Unary "+" has no effect whatsoever, even on strings. It is use +ful syntactically for separating a function name from a parenthesiz +ed expression that would otherwise be interpreted as the complete +list of function arguments. (See examples above under "Terms and List Operators (Leftward)".)
Re: u+ fails to force scalar context to empty list assignment: +( () = ... )
by LanX (Archbishop) on Mar 11, 2019 at 18:52 UTC
    to prove tybaldt's point that Unary "+" has no effect whatsoever

    #!/usr/bin/perl -w use warnings; use strict; # -------------------- # force context # -------------------- sub VOID (&) { print "VOID:\t"; $_[0]->(); return; } sub LIST (&) { print "LIST:\t"; () = $_[0]->(); return; } sub SCALAR (&) { print "SCALAR:\t"; scalar $_[0]->(); return; } # -------------------- # tests # -------------------- sub ctxt { unless (defined wantarray) { print "is void\n"; } elsif (wantarray) { print "is list\n"; } else { print "is scalar\n"; } } SCALAR { ctxt }; SCALAR { +(ctxt) }; # u+ no effect LIST { ctxt }; LIST { +(ctxt) }; # u+ no effect VOID { ctxt }; VOID { +(ctxt) };; # u+ no effect # BUT LIST { 0+(ctxt) }; # forcing scalar context

    SCALAR: is scalar SCALAR: is scalar LIST: is list LIST: is list VOID: is void VOID: is void LIST: is scalar

    (code stolen from older post)

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

      Shorter alternative:

      >perl -MO=Concise,-exec -e"$a = +f()" 2>&1 | find "entersub" 5 <1> entersub[t3] sKS/TARG >perl -MO=Concise,-exec -e"@a = +f()" 2>&1 | find "entersub" 6 <1> entersub[t4] lKS/TARG >perl -MO=Concise,-exec -e"+f()" 2>&1 | find "entersub" 5 <1> entersub[t2] vKS/TARG

      The first letter of the "word" after the op name (entersub) is the context in which it's evaluated.

        Interesting!

        > Shorter alternative:

        Well ...

        the sub ctxt() is just using the well documented wantarray the rest is only cosmetics to provide readable output.

        If I wanted to golf, I could also do:

        >perl -E"sub f{say qw/s l v/[wantarray//'2']};+f;$a=+f;@a=+f" v s l

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: u+ fails to force scalar context to empty list assignment: +( () = ... )
by LanX (Archbishop) on Mar 11, 2019 at 21:53 UTC
    > Interesting (I expected a compilation error here, similar as with number predecrement, e.g. --5):

    hmm me too.

    My theory is that the scalar aassign in the concise output returns a modifiable value, but that the compiler "forgot" to moan here.

    That's probably an implementation detail that might change in the future and break this code.

    C:\>perl -e "@a=1..5; print 0+( @a );" 5 C:\>perl -e "@a=1..5; print --( @a);" Can't modify array dereference in predecrement (--) at -e line 1, near + ");" Execution of -e aborted due to compilation errors. C:\>perl -MO=Concise -e "print --( () = /;/g );" a <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 -e:1) v:{ ->3 9 <@> print vK ->a 3 <0> pushmark s ->4 8 <1> predec sK/1 ->9 7 <2> aassign[t1] sKPRMS ->8 - <1> ex-list lK ->6 4 <0> pushmark s ->5 5 </> match(/";"/) l/RTIME ->6 - <1> ex-list lK ->7 6 <0> pushmark s ->7 - <0> stub lPRM* ->- -e syntax OK

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

Re: u+ fails to force scalar context to empty list assignment: +( () = ... )
by Marshall (Abbot) on Mar 11, 2019 at 18:33 UTC
    yet another way to force scalar context:
    use string concatenation,
    print "".( () = /;/g ); #prints "3"
    unary + doesn't do the job as tybalt89 shows.

    why not just?:

    print tr/;//;

      0+ would make more sense than "". here.

        fair enough, both work.

        As an update, string concatenation can be used in other situations to force scalar context so it is valid to mention that possibility. In this particular case, 0+ is perfect. However if the goal is only to count ";", tr is even better.

Re: u+ fails to force scalar context to empty list assignment: +( () = ... )
by ikegami (Pope) on Mar 12, 2019 at 02:19 UTC

    Interesting (I expected a compilation error here, similar as with number predecrement, e.g. --5):

    A numeric literal doesn't return an lvalue, but an assignment in scalar context returns an lvalue. See Mini-Tutorial: Scalar vs List Assignment Operator.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (5)
As of 2020-01-20 08:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?