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

Dear esteemed monks,

I feel a bit stupid on this issue. I was answering on a French Perl forum to a question in which the poster was trying to use symbolic references to store a number of file handles. I told the OP to use an array or hash of handles instead and outlined the basic syntax for it. I could not test it because it was too dependent on the OP's environment.

The OP said that it did not work. So I wrote a little demonstration program as follows:

my @in_fh; my $count = 0; while (my $line = <DATA>) { chomp $line; open my $IN, "<", $line or die "Cannot open file $line $!"; $in_fh[$count] = $IN; $count++; } my $i = 0; while ($i < $count) { while (my $line = <{$in_fh[$i]}> ) { print $line; } $i++; } __DATA__ one.txt two.txt
But the OP was right: this does not seem to be able to read anything from the two files.

I was able to work around the problem with the following syntax fix:

while (my $line = readline $in_fh[$i] ) {
but I am still puzzled at the fact that:
while (my $line = <{$in_fh[$i]}>) {
does not work properly.

When I check the content of $in_fh[$i], I get a glob: GLOB(0x60006f218), so this seems to be correct. But when trying to read the line, it returns the glob instead of the line from the file. I suspect that this is one case where the compiler is confused by the syntax and would need a hint about the syntax intent, but did not find a solution with the diamond <...> operator. I am fairly sure that I have already done something very similar with braces around the array element containing the file handle, but can't remember what it was exactly to get it to work. Any idea?

Update: fixed the off-by-one error mentioned by hdb, which was not in the original program, but added by mistake by me in the above code when slightly simplifying the code for the purpose of making it shorter for this post. (And, yes, I am using strictures.) Thanks hdb.

Replies are listed 'Best First'.
Re: Using an array of file handles
by choroba (Cardinal) on Apr 22, 2016 at 11:22 UTC
    This behaviour is documented in perlop:

    > If what's within the angle brackets is neither a filehandle nor a simple scalar variable containing a filehandle name, typeglob, or typeglob reference, it is interpreted as a filename pattern to be globbed, and either a list of filenames or the next filename in the list is returned, depending on context.

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
      Thank you choroba, yes, I more or less knew that, but I thought that enclosing the array item between curlies was enough to solve the issue. I was obviously wrong on that.

      I've used this syntax with curly brackets for writing to filehandles, quite obviously not for reading from a filehandle, contrary to what I thought to remember.

Re: Using an array of file handles
by hdb (Monsignor) on Apr 22, 2016 at 11:32 UTC

    Easy workaround:

    for my $handle (@in_fh) { while (<$handle> ) { print ; } }

    You also have an "off-by-one" error: $i <= $count which you would have spotted by using strict and warnings.

      Thank you hdb. Yes, sure, but finding a workaround was not really my problem (I actually presented one in my original post), my problem was that I was convinced that it was possible to read lines directly from something like <{$a[$c]}>, and it turns out that this was wrong.

      As for the off-by-one error, you're correct, but it's a mistake I did when trying to simplify the code for the post, I did not have the error in my slightly more complicated original code. Yes, I am using strict and warnings for all my programs (except possibly very simple one-liners).

Re: Using an array of file handles
by Athanasius (Archbishop) on Apr 22, 2016 at 13:34 UTC
      Thanks Athanasius. Yes, readline is actually what I used to work around my problem, as I mentioned in my original post, but I was looking for a solution with the diamond operator. It appears that it can't work directly with a filehanbdle that is stored as an array or hash element, so that either readline or an intermediate variable is required.