Вопрос

Is it normal to write in such way:

if(($x && $y && $z) eq "test"){

}

If I am interested in ($x eq "test") && ($y eq "test") && ($z eq "test")?

Это было полезно?

Решение

It wouldn't be normal because it doesn't even work

$x && $y returns either $x or $y depending on whether the value of $x is true or not.

That means that ($x && $y) && $z returns either $x, $y or $z depending on the values of $x and $y.

That means that only one of $x, $y or $z will be compared against 'test'.

For example, you'll get a false positive (returns true when it should return false) when you have $x='abc'; $y='def'; $z='test';.

If you wanted something shorter, then you'd have to use something like

use List::MoreUtils qw( all );

if ( all { $_ eq "test" } $x, $y, $z )

Другие советы

No.

The expression $x && $y && $z is equivalent to the expression

$x ? $x : $y ? $y : $z

and will be evaluated separately from the expression on the other side of the eq operator.

Writing if ($x eq 'test' && $y eq 'test' && $z eq 'test') ... as you do is as reasonably terse as you're going to get.

As an elaboration on ikegami's answer, I thought I would show the code for the all() subroutine, as it is rather simple, and gives a good demonstration of the logic behind the answer to the question. And also, as it happens, makes a good demonstration for how prototypes work.

sub all (&@) {
    my $f = shift;
    foreach ( @_ ) {
        return NO unless $f->();
    }
    return YES;
}

The prototypes & and @ refer to a code reference, and a list of arguments. YES and NO are constants for true and false defined as follows:

# Use pure scalar boolean return values for compatibility with XS
use constant YES => ! 0;
use constant NO  => ! 1;

The basic gist of this subroutine is to take a code reference (an anonymous subroutine) and execute it once for each argument, using $_ as the loop variable. If any argument causes the code block to return a false value, the subroutine returns false and ends.

With this code and these prototypes we can use the all subroutine much like map, with a code block first:

all { $_ eq "foo" } "foo", "bar", "baz";

If we remove the prototypes (&@), we must pass the code reference as a standalone, as part of the list:

all sub { $_ eq "foo" }, "foo", "bar", "baz";

Note the addition of the sub keyword, and the comma after the code block.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top