简体   繁体   中英

What is meaning of “Sets $_ for each item in LIST in turn” in perl function returning a scalar?

The Perl List::MoreUtils documentation says that the function true "Sets $_ for each item in LIST in turn".

That makes it sound like an iterator, but I see no way to use it as such. EG

use List::AllUtils qw(first any true);
@strings = `dir`;
printf "%i item(s) start with 1", true { substr($_,0,1) eq '1' } @strings;

prints 18.

Trying it in list mode, as if it were grep:

@ones = true { substr($_,0,1) eq '1' } @strings;

still returns just an integer.

If there is no way to retrieve the individual matches, what does the comment about $_ mean?

The same comment is used on many other List::Util and List::MoreUtils functions which return scalars, eg, all , any , etc.

The complete definition in the manual states that:

true BLOCK LIST

Counts the number of elements in LIST for which the criterion in BLOCK is true. Sets $_ for each item in LIST in turn

 printf "%i item(s) are defined", true { defined($_) } @list; 

So it does result in a scalar, representing the number of elements from LIST in which the content of the BLOCK is true. Each element will be assigned to $_ and the code in BLOCK will be executed. If the result is true, it will add to the internal count; until the whole list is finished and the total sum of true results is returned.

$_ is the "current context's value"... in your example, the block is executed with $_ set to each element from @strings.

You then test for equality of "1". So the output of the block is a list (possibly containing 18 elements) each with only "1" in each item. And then filter for only true values - of which all of them will be true - which results in the scalar-count of true elements (aka 18).

It appears you might be are in need of the "schwartzian transform" - which can capture tuples (instead of single values) per iteration, which could allow your print to access each value of $_... but it would also require a "for" or similar.

I think if you want to get the matched elements for a list, don't use this List::AllUtils thing, just use the perl 'grep' builtin (which is not the same as the grep command line program).

Something like this

my @matches = grep { substr($_,0,1) eq '1' } @strings;
my $num_matches = @matches;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM