in reply to Re: anonymous code blocks
in thread anonymous code blocks

I notice that quite a few people use:
my $somevar; open $somevar, ">", "somefile" or die "unable to open: $!\n";
I have always used:
open FILE, ">", "MYFILE" or die "unable to open:$!\n"; ... close (FILE)
after reading open, I realize that when in a sub the first is example is good because you dont have to worry about closing the filehandle - it simply goes out of scope. Does the same hold true when in MAIN? Do I not have to cose the fh? Or am I missing something?

Ted
--
"That which we persist in doing becomes easier, not that the task itself has become easier, but that our ability to perform it has improved."
  --Ralph Waldo Emerson

Replies are listed 'Best First'.
Re^3: anonymous code blocks
by philcrow (Priest) on Sep 15, 2005 at 18:20 UTC
    Yes, Perl closes open file handles when the program exits. That is the final point at which things can go out of scope.

    The real advantage of storing file handles in variables is that you don't accidentally share a file handle. With global handles, this could be a problem. By using my, the variable is limited in scope.

    Even though file handles in my variables close when their scopes end, it's considered good form to manually close the handle (and check the return status). Just because Perl could do something for you doesn't mean you should let it.

    Phil

Re^3: anonymous code blocks
by blazar (Canon) on Sep 16, 2005 at 09:22 UTC
    after reading open, I realize that when in a sub the first is example is good because you dont have to worry about closing the filehandle - it simply goes out of scope. Does the same hold true when in MAIN? Do I not have to cose the fh? Or am I missing something?
    I second that, but it's not limited to subs which introduce nothing but a "lexical scope", so the keyword here is the latter. For example you may have
    for (@files) { # open my $fh, '<', $_ or (warn "$_: $!\n"), next; push @first_lines, scalar <$fh>; }

    Or, consider the following example script that exploits open as a cheap way to parallelize a series of possibly slow operations:

    #!/usr/bin/perl use strict; use warnings; die "Usage: $0 <net>\n" unless @ARGV == 1; # Rudimentary check on the argument (my $net=shift) =~ s/\.0+$/./ or die "Supply an IP of the form <#.#.#.0>\n"; print 'Begun pings at ' . localtime, "\n"; my @p; open $p[@p], '-|', "ping -w 5 -c 5 $net$_" or die "Couldn't start ping for $net$_: $!\n" for 1..255; undef $/; print map <$_>, @p; __END__
    Note:
    • here you may want to do a stricter check on the argument to make this into a "serious" thing,
    • lexical handles are not strictly required for this to work, but they make it easier,
    • the way used to fill @p here is somewhat exotic: you may prefer something like
      my @p = map { open my $fh, '-|', "ping -w 5 -c 5 $net$_" or die "Couldn't start ping for $net$_: $!\n"; $fh } 1..255;
      Done this way, you don't even really need @p any more, you could just chain the two maps. Oh, but I'm digressing...

    In any case, to answer your question: yes! "lexical filhandles" are closed automatically on scope exit. But there are situations in which you may need to explicitly close them. If I don't need to, I don't; others' opinion may vary: see e.g. philcrow's reply.

    Also, a filehandle can hold more than regular files, and there's stuff you still have to explicitly close.