Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Sometimes it's in Void Context

by Ovid (Cardinal)
on May 31, 2002 at 22:43 UTC ( [id://170848]=perlquestion: print w/replies, xml ) Need Help??

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

In answering a question on the Perl Beginner's list, I stumbled across the following:

#!/usr/bin/perl -w $lines[0] = [ qw/ dog cat bird / ]; print $lines[0][0,1,2];

No, it's not an array slice. The "0,1,2" is a list and each element of the list is evaluated from left to right and the results of the last evaluation (2) are returned. Thus, the above snippet prints "bird", but issues no warnings.

However, if I change the 1 to a 2:

#!/usr/bin/perl -w $lines[0] = [ qw/ dog cat bird / ]; print $lines[0][0,2,2];

I get the following:

Useless use of a constant in void context at C:\test.pl line 3. bird

chromatic guessed that this may be a hack in Perl to allow us to put 1 at the bottom of modules without a warning, but I'm not sure. Is this documented anywhere, or is it a bug?

Cheers,
Ovid

Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Replies are listed 'Best First'.
Re: Sometimes it's in Void Context
by chromatic (Archbishop) on Jun 01, 2002 at 02:22 UTC
    Try it with 'diamond' or 'iguana' and it will also be silent!

    I was half right. The warning comes from op.c, specifically Perl_scalarvoid. When it hits a constant op, it checks to see if it should throw a bareword warning. Otherwise, if it needs to warn about useless constants in void context, it does. There's a hack, though, like I thought, but the comment says:

    /* the constants 0 and 1 are permitted as they are conventionally used as dummies in constructs like 1 while some_condition_with_side_effects; */
Re: Sometimes it's in Void Context
by dws (Chancellor) on May 31, 2002 at 23:07 UTC
    Ah, but you are dealing with a slice, once you dereference the reference. Try   print @{$lines[0]}[0,1,2]; As to why you're seeing the behavior you are... uh... uh...

    Update: Oh bother. I misunderstood the meta-problem.

      Heh :) Even though your answering a totally different question, it does raise another issue. Why are the following three cases treated differently?

      $lines[0] = [ 3,2,1 ]; print $lines[0][ 3,2,1 ]; print @{$lines[0]}[ 3,2,1 ];

      Ignoring, for the moment, the "Useless use of constant in void context" warnings, how does Perl know that the first use of [ 3,2,1 ] is to generate a reference to an anonymous array from a list, while the second example doesn't reduce to this:

      print $lines[ARRAY(0x1a7efd8)];

      We have the same issue with the third example recognizing that [ 3,2,1 ] is to be used as a list of array indices for the slice.

      This behavior should is difficult to keep straight:

      $lines[0] = [ "dog", "cat" ];

      Why doesn't that just assign "cat" to the first element of @lines? My assumption is that it is because the square brackets are performing a subtle double-duty. In this example:

      print $lines[0][0,1];

      the square brackets are being used to indicate an array element. In another example:

      $lines[0] = [ "dog", "cat" ];

      the square brackets are being used to create a reference to an anonymous array and constructs the anonymous array from a list. Keeping things straight can be a major headache, which is why I'm glad Perl does it for me :)

      Cheers,
      Ovid

      Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

        Okay, lemme know if I'm wrong here, but:
        $lines[0] = [ 3,2,1 ];
        The brackets are forming an array context. You're assigning an array to the array member
        print $lines[0][ 3,2,1 ];
        I am assuming what is going here is that the array dereference is looking for a numerical value to figure out where to look in the array. You get the same error here:
        print scalar(4,5); jaybonci@starlite:~/perl/pm$ ./array.pl Useless use of a constant in void context at ./array.pl line 6. 5jaybonci@starlite:~/perl/pm$
        Looking at the comma operator in the perlop page, this makes sense. The values are evaluated one by one.

        It wouldn't make sense for perl to be looking for an array in a dereference operator, because you need a numerical value. Why would it map those values or try to return a sub array based on those values. The execution order says to resolve the commas first.

        Like I said, I could be way off.

            --jb
        Why are the following three cases treated differently?

        I suspect it is because the parser expects different things at the different times. Look at the first one for example, it is pretty reasonable for this to be a 3-element array, we often make such assignments. In fact, for us to be able to make such assignments, this has to be a three element array.

        In the second case the parser is looking for a subscript instead of another array, so it tries to make what it finds into one.

        HTH, --traveler

        I don't see the issue here, sorry.

        $lines[0] = [3,2,1]: here we agree that [3,2,1] must mean an array reference.

        $lines[0][3,2,1]: I fail to see how this can parse as something like ``$lines[ARRAY(0x1a7efd8)]'' (i.e. [3,2,1] becomes an array reference, which is "numericalised" into the value 0x1a7efd8. For that, you'd need an extra set of square brackets: the inner pair delimits an array reference, the outer pair delimits an array index! Indeed, testing $lines[0][[3,2,1]] shows that it behaves as a numericalised array reference.

        I can see nowhere in the "grammar" of Perl (I use the term loosely...) where both a scalar value (such as an array reference!) and an array subscript are legal. So there's no problem here.

(MeowChow) Re: Sometimes it's in Void Context
by MeowChow (Vicar) on Jun 03, 2002 at 02:58 UTC
Re: Sometimes it's in Void Context
by ysth (Canon) on Sep 12, 2004 at 21:15 UTC
    This was recently actually documented in perlop by David Nicol:
    =head2 No-ops Perl doesn't officially have a no-op operator, but the bare constants C<0> and C<1> are special-cased to not produce a warning in a void context, so you can for example safely do 1 while foo();

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (6)
As of 2024-03-19 09:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found