Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Forcing list context. Brackets (with list within) as an unary right-associative operator

by rsFalse (Hermit)
on Mar 01, 2019 at 13:00 UTC ( #1230712=perlquestion: print w/replies, xml ) Need Help??

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

Hello,

Here I'll write a collection of ways how to force list context, and next I will write some examples of using construction '( LIST )[ LIST ]', where brackets used as unary right-associative list-context forcing operator.

Some links, which are (or can be) related to this topic:
! Context tutorial
use of parentheses around a variable
Scalar Vs. List context
If you believe in Lists in Scalar Context, Clap your Hands
(Answered) How to force list context?

So, e.g., I have a code
perl -wle 'print ":" . XXX'
, where XXX is something what I want in LIST context. The concatenation dot '.' forces scalar context. (In this example, '.' changing to ',' would solve a task well). In examples I'll use regex match '/./g' for XXX (upd2. match (m) has different behavior depending on context).
perl -wle '$_ = "345678"; print ":" . /./g'
Match in scalar context, outputs ':1' (upd1. '1' stays for successful match, i.e. "logical true")

List of ways to force a list context:
perl -wle '$_ = "345678"; print ":" . ( () = /./g )' # output: ':6' (6 - number of matches; special behaviour)
'()=' list assignment operator forces list context. Must be parethessized because '.' precedence is higher than of assignment.
perl -wle '$_ = "345678"; print ":" . @{[ /./g ]}' # output: ':6' (6 - number of matches => number of array elements)
perlsecret Babycart op. Referencing + dereferencing.
perl -wle '$_ = "345678"; print ":" . @_{ /./g }' #Use of uninitialized value in concatenation (.) or string at -e line +1. #:
Taking a slice of hash ( %_ ). May be any hash. For viewing how match have run, we can add '/.(?{ print $& })/g'.
perl -wle '$_ = "345678"; print ":" . ( /./g )[ 1 ]' # output: ':4' (second match for e.g. index 1)
Asking some list elements (e.g. one element, e.g. which index is '1').

Speed of different methods.
I tried these four methods for a string of length 5e5.
perl -wle '$_ = "3" x 5e5; print ":" . method( XXX )'
Both first and second ways consumed 0.33 s, and 3rd and 4th ways consumed 0.25 s.
I think this is because: former ways manipulate every element of a list generated by match, and later ways try to access only one element of some structure.

Asking for no elements of the list by using something inside "brackets operator".
I name brackets as an operator, but I do not know it a true operator? Also, I haven't seen it in perlop operator precedence list.
Here are some ways how to ask none of elements:
perl -wle '$_ = "345678"; print ":" . ( /./g )[ [] ]' #Use of uninitialized value in concatenation (.) or string at -e line +1. #:
Simply concatenates with uninitialized value which self-stringifies into ''. Same with perl -wle '$_ = "345678"; print ":" . ( /./g )[ {} ]'.
perl -wle '$_ = "345678"; print ":" . ( /./g )[ undef ]' #Use of uninitialized value in list slice at -e line 1. #:3
Uninitialized value inside list (inside-bracket list), which casts to numeric and becomes 0, so first element of a list (target list), i.e. 3, is returned.

And for these two I get strange behavior:
perl -wle '$_ = "345678"; print ":" . ( /./g )[()]' #Argument ":" isn't numeric in list slice at -e line 1. #:3
perl -wle '$_ = "345678"; print ":" . ( /./g )[@_]' #Argument ":" isn't numeric in list slice at -e line 1. #:3
In these two, it seems that a 'colon' is cloned and transported into brackets and evaluated here. It evaluates to numerioc, i.e. 0, and returns first element of a list, i.e. 3.
Here, if we use some number instead of colon, we can get unexpected behavior (with no warnings):
perl -wle '$_ = "345678"; print "2" . ( /./g )[()]' #25
'5' stands for 3rd element, i.e. index = 2.
perl -wle '$_ = "345678"; print "2" . ( /.(?{ print $& })/g )[()]' 3 4 5 6 7 8 25
  • Comment on Forcing list context. Brackets (with list within) as an unary right-associative operator
  • Select or Download Code

Replies are listed 'Best First'.
Re: Forcing list context. Brackets (with list within) as an unary right-associative operator
by choroba (Archbishop) on Mar 01, 2019 at 13:31 UTC
    Interesting. Definitely a bug in Perl, but it seems it's been already fixed:
    $ blead perl -wle '$_ = "abcdefgh"; print "2" . ( m/./g )[()]' Use of uninitialized value in concatenation (.) or string at -e line 1 +. 2

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

      Hm... it seems like this might be #126193, fixed by 9e59c36b (at least that's what a bisect says), fix released with Perl v5.24.

      Ah, nice. I have it on my v5.18.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (5)
As of 2020-01-23 13:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?