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

I'm looking for an explaination as to why this code fails, but a seemingly superfluous change makes it ok. This is broken
$file_h{$temp1} = "$temp2"; open($file_h{$temp1}, "< $file"); $line = <$file_h{$temp1}>;
However, if the last line is replaced by
$fh = $file_h{$temp1}; $line = <$fh>;;
then all is well. Ideas?

Replies are listed 'Best First'.
(tye)Re: Please explain: A hash of file handles peculiarity
by tye (Sage) on Jan 30, 2001 at 10:00 UTC

    The <...> operator can mean ...->readline() or glob("..."). Perl has to decide which of those two you wanted. <BAREWORD> always means readline() as glob("BAREWORD") isn't very useful. <*.c> always means glob() since "*.c" isn't ever going to be a file handle.

    Now, things like <$scalar>, <$array[0]>, <$hash{KEY}> were harder to call. For some reason that I'm not completely sure of, it was decided that the first would always be readline() and all others would be glob(). I think this is generally acknowledged as not an ideal design decision, but we are stuck with it.

    So I tend to never use <> when I mean glob() and to write $hash{KEY}->readline() when my file handles aren't simple like <FILE> or <$fh>. I was surprised to find Perl smart enough to make this work even when I didn't create file handles with an IO::* module. I'm not sure how smart it is, though, so using a module is probably a good idea.

            - tye (but my friends call me "Tye")
Re: Please explain: A hash of file handles peculiarity
by japhy (Canon) on Jan 30, 2001 at 09:49 UTC
    Perl demands that whatever appears inside the <> operator be a simple scalar value -- no subscripts or expressions allowed. You've "stumbled" upon a common workaround for this limitation. Another one would be to use a module like IO::Handle or IO::File, so that you can use the readline method of the objects instead.

    japhy -- Perl and Regex Hacker
Re: Please explain: A hash of file handles peculiarity
by repson (Chaplain) on Jan 30, 2001 at 09:49 UTC
    The problem is based around the fact that the < > structure is used for globbing as well as reading. Therefore anything other than a simple variable or bareword, confuses perl. The solution (from memory) is to enclose the contents in braces or (slightly clearer) use the underlying function readline.
    # $line = <$file_h{$temp1}>; $line = < {$file_h{$temp1}} >; $line = readline($file_h{$temp1});