Under what circumstances is “not” different from “if not”?

I used to think that unless

and are if not

completely equivalent, but this Q&A made me realize that they can lead to different conclusions in the context of a list

use strict;
use warnings;
use Data::Printer;
use feature 'say';

my %subs = (
              unless => sub {
                            my ( $value ) = @_ ;

                            return "$value is a multiple of 3"
                              unless $value % 3 ;
                        },
              if_not => sub {
                            my ( $value ) = @_ ;

                            return "$value is a multiple of 3"
                              if not $value % 3 ;
                        },
           );

for my $name ( keys %subs ) {

    my $sub = $subs{$name};
    say $name;
    my @results = map { $sub->($_) } 1 .. 10;
    p @results;
}

      

Output

if_not
[
    [0] "",
    [1] "",
    [2] "3 is a multiple of 3",
    [3] "",
    [4] "",
    [5] "6 is a multiple of 3",
    [6] "",
    [7] "",
    [8] "9 is a multiple of 3",
    [9] ""
]
unless
[
    [0] 1,
    [1] 2,
    [2] "3 is a multiple of 3",
    [3] 1,
    [4] 2,
    [5] "6 is a multiple of 3",
    [6] 1,
    [7] 2,
    [8] "9 is a multiple of 3",
    [9] 1
]

      

In the above code snippet shows that unless

and if not

lead to the fact that the routine displays a different value of the last expression evaluated.

It seems that this is because he if not

considers him not

part EXPR

, while he unless

does not consider him part EXPR

.

Question

Are there any other code examples where the two are not synonymous?

+3


source to share


1 answer


The difference is that for your case unless

expression to the latest estimates $value % 3

, while for your event if not

expression with the last assessmentnot $value % 3

not

behaves like a simple operator, whereas if

and unless

are language constructs such as while

and for

that do not participate in the meaning of expressions

In any case, it is bad practice to rely on the return value of a subroutine if it has no return

path for every path or ends up with an expression. perldoc perlsub

talks about it

If not found return

, and if the last statement is an expression, its value is returned. If the last statement is a loop control structure such as foreach

or while

, no return value is specified.



So, just because you think you know what a subroutine will evaluate without return

, it won't actually be reliable unless you end your subroutine with an expression and change it in later versions of Perl.

Just write return

your condition for a different case, and your code will become clearer. Or, you can use a conditional expression that specifies the return value for both conditions.

cond_exp => sub {
    my ( $value ) = @_;

    $value % 3 ? "" : "$value is a multiple of 3";
}

      

+3


source







All Articles