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

I hope this is not too dumb a question :-) While working on a dictionary module, I came up with the following question: Why is $_ not set in a while loop like the following one? I would expect it to work like while (<>) { # do stuff }

while (match('a')) { print "- $_\n"; # $_ is undef all the time }

I can fix it using a loop variable, but it doesn't look as sexy and it doesn't help me to understand why the first option doesn't work.

while (my $entry = match('a')) { print "- $entry\n"; # prints the correct results }
Here's an example match function to let you understand what it's all about. When having searched all entries, the function returns undef. (Note that in the original problem match returns a reference, but the problem is the same.)
my $matchPos = 0; sub match { my ($key) = @_; while ($matchPos < @data) { $matchPos++; return $data[$matchPos - 1] if ($data[$matchPos - 1] =~ /$key/); } return undef; } while (match('a')) { print "- $_\n"; }

Replies are listed 'Best First'.
Re: When does while set $_ ?
by jmcnamara (Monsignor) on Aug 01, 2002 at 08:09 UTC

    This is explained in perlop in relation to <>:
    Ordinarily you must assign the returned value to a vari­ able, but there is one situation where an automatic assignment happens. If and only if the input symbol is the only thing inside the conditional of a `while' state­ ment (even if disguised as a `for(;;)' loop), the value is automatically assigned to the global variable $_.
    --
    John.

      Thanks, John. I did read the man pages, but didn't find this one. I guess I just naturally assumed that the while statement should assign $_.

      Is there any (simple) way to assign the outer $_ inside the match() function when in a while-loop? Or would that involve some major hacking?


        You could localise $_ as follows:
        while (local $_ = match('a')) { print "- $_\n"; }

        However, it would be better to use grep() instead of your match() function. Then all of your code could be replaced with the following line: ;-)     print "- $_\n" for grep {/a/} @data;

        --
        John.

Re: When does while set $_ ?
by Anonymous Monk on Aug 01, 2002 at 08:06 UTC
    it is known special case that
    while (<FILEHANDLE>) { }
    made to read into $_ variable. Either save it's value by "local" operator, or use following special-case construct:
    while ($var_to_receive_a_line = <FILEHANDLE>) { }