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

Right, this is a part of my code:
my $from = ""; if (@movement == (0, 1)) {$from = "north"} elsif (@movement == (1, 0)) {$from = "east"} elsif (@movement == (0, -1)) {$from = "south"} elsif (@movement == (-1, 0)) {$from = "west"}
@movement is set somewhere before and it can only have the shown values.
Depending on it's value, I need to find a wind direction.
For some reason, Perl keeps saying
Useless use of a constant in void context at D:\data\Proggen\perl\mtgr +pg\FOE.PM line 149.

This is the last elsif line shown.
Why is it useless?
The $from variable is to be used somewhere below.

Replies are listed 'Best First'.
Re: Strange "Useless use of constant" message: should not appear at all!
by japhy (Canon) on May 10, 2004 at 21:45 UTC
    You can't do array comparisons like that. You're getting the warning because @x == (1,2) is evaluating (1,2) in scalar context. The comma operator, in scalar context, evaluates its left-hand operand and discards its value, and returns its right-hand operand. So the 1 is useless.

    Perhaps you want:

    if ("@movement" eq "1 0") { ... } elsif ("@movement" eq "0 1") { ... } # etc.
    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;
Re: Strange "Useless use of constant" message: should not appear at all!
by blokhead (Monsignor) on May 10, 2004 at 21:49 UTC
    @movements == (0, 1);
    You can't compare arrays/lists for equality directly. The == and eq operators work on scalars, so @movement and (0, 1) are both being evaluated in scalar context. Of course, (0, 1) in scalar context simply throws away the 0, which is the source of the error.

    If you want to compare these arrays for equality, since they are so simple, you can stringify them:

    local $" = ","; if ("@movement" eq "0,1") { ... } elsif ("@movement" eq "1,0") { ... } ...
    Or a more general comment, even use a lookup table:
    local $" = ","; my %dir = ( "0,1" => "north", "1,0" => "east", "0,-1" => "south", "-1,0" => "west" ); $from = $dir{"@movement"};

    blokhead

Re: Strange "Useless use of constant" message: should not appear at all!
by Juerd (Abbot) on May 10, 2004 at 22:45 UTC

    Others have pointed out what is wrong with your code. Some have suggested interpolating the array, which I think is a good strategy here.

    However, I haven't seen ?: in this thread yet. Which is strange, as all this if/elsif/... thing seems to do is assign to $from.

    my $from = "@movement" eq '0 1' ? 'north' : "@movement" eq '1 0' ? 'east' : "@movement" eq '0 -1' ? 'south' : "@movement" eq '-1 0' ? 'west' : die "Unknown direction: (@movement)";

    I probably wouldn't use a lookup hash here. Redundancy's not so bad with only 4 items.

    Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Re: Strange "Useless use of constant" message: should not appear at all!
by Joost (Canon) on May 10, 2004 at 21:52 UTC
    Please note that this:
    if (@movement == (0, 1)) {$from = "north"}
    is equivalent to
    if (@movement == ($any_other_value, 1)) {$from = "north"}
    Because it only tests the equivalence between the last element of the list and the array. update: no it doesn't; see above.

    You probably want something like

    my $from = ""; if ($movement[0] == 0 && $movement[1] == 1) {$from = "north"} elsif ($movement[0] == 1 && $movement[1] == 0) {$from = "east"} elsif ($movement[0] == 0 && $movement[1] == -1) {$from = "south"} elsif ($movement[0] == -1 && $movement[1] == 0) {$from = "west"}
    This also solves your warning by the way.

    Hope this helps
    Joost

Re: Strange "Useless use of constant" message: should not appear at all!
by cLive ;-) (Prior) on May 10, 2004 at 21:50 UTC
    Perhaps you should run this:
    my @movement = (0, 1); my $from = ""; if (@movement == (0, 1)) {$from = "north"} elsif (@movement == (1, 0)) {$from = "east"} elsif (@movement == (0, -1)) {$from = "south"} elsif (@movement == (-1, 0)) {$from = "west"} print "$from\n";
    Then read up on == working on numerical values :)

    cLive ;-)

Re: Strange "Useless use of constant" message: should not appear at all!
by Sandy (Curate) on May 10, 2004 at 21:53 UTC
    Your code is not a functioning programming.

    Within the if statement, @movement is evaluated in scalar context, and consequently gives a number that is the size of the array.

    #!/usr/bin/perl -w my @movement = (0,1); my $from = ""; if (@movement == 2) {$from = "north"} elsif (@movement == (1, 0)) {$from = "east"} elsif (@movement == (0, -1)) {$from = "south"} # elsif (@movement == (-1, 0)) {$from = "west"} print "\$from = <$from>\n";
    gives "north" as the answer.

    Similarly, the list, (not array) of  (0,1) returns the last thing in the list.

    The 'useless use of number in void context' happens when numbers in the list (not the last one) are thrown away. For some reason this doesn't happen if the number thrown away is a 'zero'.

    Example 1

    my @movement = (0,1); my $from = ""; if (5 == (3,4,5)) {$from = "north"} elsif (@movement == (1, 0)) {$from = "east"} elsif (@movement == (0, -1)) {$from = "south"} # elsif (@movement == (-1, 0)) {$from = "west"} print "\$from = <$from>\n";
    gives
    Useless use of a constant in void context at ./t.pl line 4. Useless use of a constant in void context at ./t.pl line 4. $from = <north>
    Example 2
    #!/usr/bin/perl -w my @movement = (0,1); my $from = ""; if (5 == (0,0,5)) {$from = "north"} elsif (@movement == (1, 0)) {$from = "east"} elsif (@movement == (0, -1)) {$from = "south"} # elsif (@movement == (-1, 0)) {$from = "west"} print "\$from = <$from>\n";
    $from = <north>

    I'm not quite sure why the  (@movement == (1,0)) doesn't give a warning, but the  (@movement == (-1,0)) does.

    Example 3

    #!/usr/bin/perl -w my @movement = (0,1); my $from = ""; if (@movement == (1, 0)) {$from = "east"} if (@movement == (-1, 0)) {$from = "west"} print "\$from = <$from>\n";
    Gives
    Useless use of a constant in void context at ./t.pl line 5. $from = <>

    Sandy

    UPDATE:

    Looking at a previous post, I thought that I misunderstood how @movement would be read within the if statement.

    Does it compare the last element of @movement with the list within the if block. This little test says no, unless I am missing somehting?

    #!/usr/bin/perl -w my @movement = (0,1); my $from = ""; if (@movement == (0,1)) {$from = "east"} print "\$from = <$from>\n";
    Gives
    $from = <>
Re: Strange "Useless use of constant" message: should not appear at all!
by tinita (Parson) on May 11, 2004 at 10:15 UTC
    others have addressed your problem, however, the reason for the warning only showing up at the last of the elsif's can be shortened to this:
    perl -wle'-2; -1; 0; 1; 2;' Useless use of a constant in void context at -e line 1. Useless use of a constant in void context at -e line 2. Useless use of a constant in void context at -e line 5.
    1 or 0 in void context aren't treated as useless. that's why you can write 1; at the end of a module, and, uhm, i can't think of an example for the zero at the moment...
Re: Strange "Useless use of constant" message: should not appear at all!
by neniro (Priest) on May 10, 2004 at 21:40 UTC
    A small change and it's okay:
      Hmm, I first ++ voted your message after testing it and your small change, which you have now deleted, seems to work. Strange, but thank you!

      Update: Well, it did at first sight.
        Sorry, but it seems that you can't compare arrays directly to lists (thats why I removed my original post). Meantime there are a lot of good suggestions below. Using a lookup-hash is a fine idea.