perl

Why does making an assignment inside an if statement evaluate differently from making the assignment beforehand


I am assigning a variable to the first element of a list.

If I make the assignment inside an if statement, I get a different value than if I assign it outside the statement.

Like this:

$ perl -E 'my @y = (0, 1) ;  my $ x; if (($x) = @y) {say qq[yes ], $x} else {say q[no ], $x}'
yes 0

vs

$ perl -E 'my @y = (0, 1) ; my ($x) = @y; if ($x) {say qq[yes ], $x} else {say q[no ], $x}'
no 0

Why are the results different?

Is there a way to make the assignment inside the if statement and check its value?


Solution

  • The if-condition imposes a scalar context on your statement. The results are different because in the first one-liner you do:

    if (2)      # return value = @y (size)
    

    And in the second case you do:

    if (0)      # return value = $x (value)
    

    The return value of the statement ($x) = @y is not the value of $x, it becomes the size of @y. Like in the list counting idiom:

    my $n = () = (list here);
    

    Except in your case the first scalar assignment is implicit:

    if-context = ($x) = @y
    

    You finish with an additional question: Is there a way to make the assignment inside the if statement?

    Yes, you can use the array value directly and not use list assignment.

    if ( $x = $y[0] )     # the return value of the statement is 0
    

    You can also use a subscript

    if ( $x = (@y)[0] )   # the return value of the statement is 0
    

    You can shift a value off the array, though this changes the array of course.

    if ( $x = shift @y )