b4swine has asked for the wisdom of the Perl Monks concerning the following question:

The perl manual says
There is no equivalent operator to force an expression to be interpolated in list context because in practice, this is never needed. If you really wanted to do so, however, you could use the construction @{[ (some expression) ]}, but usually a simple (some expression) suffices.
I wanted to see if there are at least three a's in "baa baa black sheep", so I write:
print (('baa baa black sheep' =~ /a/g) >= 3 ? 'more' : 'less');
This doesn't work, but obviously the @{[...]} strategy does work. Is there any simpler way?

Replies are listed 'Best First'.
Re: Counting matches.
by ikegami (Patriarch) on Dec 07, 2007 at 08:06 UTC

    /g in scalar context (as imposed by >=) only returns the next match. This allows people to do something like

    while (/a/g) { ... }

    Since the result of a list assignment in scalar context is the number of elements in the assigned list, the trick is to assign the result of the match to a list, even an empty one, and place that assignment in scalar context.

    my $count = () = 'baa baa black sheep' =~ /a/g;

    Or as it applies here,

    print( ( () = 'baa baa black sheep' =~ /a/g ) >= 3 ? 'more' : 'less' ) +;

      If anyone is interested in more uses of list assignments in scalar context, consider functions that need to be able to return any scalar while also able to signal some special condition.

      In C++, you might very well do something like

      bool next(Type& arg) { if (...) { return false; } else { arg = ...; return true; } } while (i->next(arg)) { ... }

      You could do the same in Perl

      sub next { my $self = $_[0]; our $arg; local *arg = \$_[1]; if (...) { return 0; } else { $arg = ...; return 1; } } while ($i->next($arg)) { ... }

      But another solution is to return either 1 scalar or 0 scalars.

      sub next { my ($self) = @_; if (...) { return; } else { return ...; } } while (my ($arg) = $i->next()) { ... }

      One might be tempted to do the following, but it won't work if the function can return a false value (such as 0, "0", "", undef, etc).

      while (my $arg = $i->next()) { ... }
Re: Counting matches.
by poolpi (Hermit) on Dec 07, 2007 at 11:36 UTC
    $_ = 'baa baa black sheep'; my $length = 3; print tr/a// >= $length ? 'OK' : 'NOK';
    PooLpi
Re: Counting matches.
by sh1tn (Priest) on Dec 07, 2007 at 12:39 UTC
    Use intermediate list context:
    print (($counter = () = /a/g) >= 3 ? 'more' : 'less');