http://www.perlmonks.org?node_id=1016879


in reply to Re^3: Using grep and glob to find directories containing file
in thread Using grep and glob to find directories containing file

Despite the admonition not to use <> for globbing?

So...list context on the left, which then creates an anonymous array, which array, when evaluated in boolean/scalar context, produces the length of the array?

Replies are listed 'Best First'.
Re^5: Using grep and glob to find directories containing file
by LanX (Saint) on Feb 04, 2013 at 00:52 UTC
    > So...list context on the left, which then creates an anonymous array, which array, when evaluated in boolean/scalar context, produces the length of the array?

    No arrays involved, not even anonymous!

    It's just a list-assignment in scalar context.

    I would say much more performant than the former solution.

    Cheers Rolf

    PS:

    > Despite the admonition not to use <> for globbing?

    Source?

Re^5: Using grep and glob to find directories containing file
by 7stud (Deacon) on Feb 04, 2013 at 01:26 UTC

    Then I don't understand. If there's no anonymous array somewhere, then there's no counting going:

    use 5.012; my $x = ('a', 'b', 'c'); say $x; --output:-- 'c'
    Lists don't return their length in scalar context--only arrays return their length in scalar context. Although, now I see it has the same effect in your example--because in list context glob() returns an empty list when there are no matches, and trying to retrieve the last element of an empty list is undef or some other false value.

      That's not a list, that's the comma operator in scalar context, which will disregard its left hand value and return its right hand value.

      So in my $x = ('a', 'b', 'c');, 'a' and 'b' get discarded, and 'c' gets assigned to $x, as your snippet proves. This behaviour is documented (see the link I gave) and also demonstrated by B::Deparse:

      $ perl -MO=Deparse -E '$x = ("a", "b", "c");' use feature 'current_sub', 'evalbytes', 'fc', 'say', 'state', 'switch' +, 'unicode_strings', 'unicode_eval'; $x = ('???', '???', 'c'); -e syntax OK

      However, =()= is an idiomatic way to enforce list context. The details are better explained in Perl Idioms Explained - my $count = () = /.../g than I could do it myself, but just to demonstrate that it works, consider the following.

      $ perl -MO=Deparse -E '$x =()= ("a", "b", "c"); print $x' use feature 'current_sub', 'evalbytes', 'fc', 'say', 'state', 'switch' +, 'unicode_strings', 'unicode_eval'; $x = () = ('a', 'b', 'c'); print $x; -e syntax OK $ perl -E '$x =()= ("a", "b", "c"); print $x' 3
      > Lists don't return their length in scalar context

      Correct!

      With "goatse" it's a list _assignment_ = which in scalar context returns the number of list elements assigned.

      But this was a scalar assignment.

      >  my $x = ('a', 'b', 'c');

      The LHS of the assignment operator decides about the context.

      An example of scalar context of list context of assignment is

       while ( ($v,$k) = each %h )

      It will terminate as soon as each returns an empty list, not when the lists last element (here $k) is undef.

      Clearer now?

      Cheers Rolf

      PS: you replied to yourself twice.

      UPDATE

      I think analyzing the op-tree helps understanding the mechanism

      lanx@nc10-ubuntu:~/org$ perl -MO=Terse -e'$x= ()=qw(a,b)' LISTOP (0x9bd0fe0) leave [1] OP (0x9be01e8) enter COP (0x9bb8860) nextstate BINOP (0x9b3ca48) sassign BINOP (0x9b21a58) aassign [2] UNOP (0x9b218c0) null [142] OP (0x9be3e40) pushmark SVOP (0x9c14638) const [3] PV (0x9b1dee0) "a,b" UNOP (0x9c14598) null [142] OP (0x9b19820) pushmark OP (0x9b3c980) stub UNOP (0x9be8630) null [15] PADOP (0x9b21940) gvsv GV (0x9b1dec0) *x -e syntax OK

      (don't blame me for Larry's decision to call a list assignment aassign)

      You see assignment BINOP is like a function called with arguments (RHS,LHS) and RHS is evaluated according to LHS context and assigned to LHS. (thats decided a compile time)

      The RHS of the first BINOP is the second BINOP, not a list.

      That's not a list

      Are you sure? "Learning Perl 6th ed", p. 46 says:

      A list literal (the way you represent a list value within your program) is a list of comma- separated values enclosed in parentheses. These values form the elements of the list. For example:
      
      (1, 2, 3) # list of three values 1, 2, and 3
      

      This behaviour is documented (see the link I gave)

      …which says:

      Binary "," is the comma operator…
      
      In list context, it's just the list argument separator, and inserts both its arguments into the list.