http://www.perlmonks.org?node_id=1013273

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

I have a script with the following two lines:
open $files{ "foo" }, " > xyz"; print { $files{ "foo" } } "done\n"; close { $files{ "foo" } };
since both print and close take a FILEHANDLE, I would expect these to work. However the print works fine and writes to the desired file handle, but the close fails with:
"Not a GLOB reference at ..."
I do not know what a GLOB is. Is there a simple way to close this file that works?

Replies are listed 'Best First'.
Re: filehandle for close
by eyepopslikeamosquito (Archbishop) on Jan 14, 2013 at 21:05 UTC

    You need to lose the braces around the argument to close because Perl is interpreting that as an anonymous hash (as "use warnings" will tell you). This works for me:

    use strict; use warnings; my %files; open $files{"foo"}, '>', "xyz" or die "open failed: $!"; print { $files{"foo"} } "done\n" or die "print failed: $!"; # close { $files{"foo"} }; # oops: 'Odd number of elements in anony +mous hash' close $files{"foo"}; # works ok

Re: filehandle for close
by zbest (Initiate) on Jan 14, 2013 at 21:04 UTC
    Purely by trial and error I figure the following works:
    open $files{ "foo" }, " > xyz"; print { $files{ "foo" } } "done\n"; close *{ $files{ "foo" } };
    I would love to understand why, though. It is not obvious to me from the documentation.

      The Perl print function, which has a long history and a tricky syntax, takes an optional file handle as its first argument. Without the optional first file handle argument, it prints to the default output handle (typically STDOUT). Moreover, it has a special syntax where its first and second arguments are separated not by a comma (like most Perl functions) but by a space! And because your first argument to print is more complex than a plain scalar variable, you need to specify it in a bare block, for, erm, historical reasons. Note that this special block syntax to print is clearly documented:

      If you're storing handles in an array or hash, or in general whenever you're using any expression more complex than a bareword handle or a plain, unsubscripted scalar variable to retrieve it, you will have to use a block returning the filehandle value instead
      However, you then made the (perfectly understandable) "mistake" of assuming that this special print syntax applies to other Perl functions, such as close. When calling most Perl functions, you should not place the first function argument in a block; this is a one-off special case for the print function.

Re: filehandle for close
by blue_cowdawg (Monsignor) on Jan 14, 2013 at 20:45 UTC
        Is there a simple way to close this file that works?

    Show us how you assigned a file handle to that hash...


    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
Re: filehandle for close
by razzmataz (Novice) on Jan 15, 2013 at 14:45 UTC

    Try this:

    use IO::File; my %files; $files{"foo"} = IO::File->new(">xyz"); print { $files{"foo"} } "done\n"; $files{"foo"}->close;