7

I think none subroutine from List::MoreUtils does not act as described. According to documentation,

none BLOCK LIST Logically the negation of any. Returns a true value if no item in LIST meets the criterion given through BLOCK, or if LIST is empty. Sets $_ for each item in LIST in turn

Now, try:

use strict;
use warnings;
use 5.012;
use List::MoreUtils qw(none);

my @arr = ( 1, 2, 3 );
if ( none { $_ == 5 } @arr ) {
    say "none of the elements in arr equals 5";
}
else {
    say "some element in arr equals 5";
}

works OK, but replace @arr with an empty one (my @arr = (); or simply my @arr;) and you get a wrong answer.

What's going on?

update: i had List::MoreUtils ver 0.22. Updated to the latest and it seems OK. Weird though!

David B
  • 29,258
  • 50
  • 133
  • 186

1 Answers1

9

The documentation is in line with the v 0.33 pure Perl implementation. The reason why it failed was because the implementation changed between versions 0.22 and 0.33.

In v 0.33, if @array is empty, the for loop will not execute, so YES will be returned.

Here are the two versions side-by-side:

# v 0.33                      |  # v 0.22
------------------------------+----------------------------------------
sub none (&@) {               |  sub none (&@) {
    my $f = shift;            |      my $f = shift;
    foreach ( @_ ) {          |      return if ! @_;          # root cause
        return NO if $f->();  |      for (@_) {
    }                         |          return 0 if $f->();
    return YES;               |      }
}                             |      return 1;
                              |  }

MetaCPAN also provides a comprehensive diff between versions 0.22 and 0.33

Zaid
  • 36,680
  • 16
  • 86
  • 155