in reply to Resource management

Perl has no exact equivalent of Java's "try-with-resources" mechanism, partly because Perl's exception management is different (e.g. the native open and close don't normally throw an exception, but return false values, so program flow can be handled differently) and because Perl does not have an equivalent of Java's interface java.io.Closeable. Although lexical file handles are closed automatically when they are destroyed, this might not be true for some tied file handles, and although Perl's reference counting means that the time at which objects are destroyed is much more reliable than in Java, I would still not recommend relying on DESTROY for everything*. This is because accidental circular references would prevent objects from being a garbage collected, and also, if one forgets to discard objects early enough, trying to clean up resources during global destruction can cause problems. Another issue is that the different kinds of resources you mentioned have different APIs, so the code to clean them up will be different. So unfortunately the answer to your question is that there is no single idiom built into Perl that applies to all the different resources you mentioned, other than closing them explicitly.

However, Perl is of course a very flexible language that allows you to implement some kind of idiomatic/unified resource handling, if you like. How you would best do that depends on the details of your code, e.g. is it OO or not and what kind of resources specifically do you want to manage? Another thing that comes to mind is Try::Tiny, which gives you a nice little try/catch/finally mechanism.

* Update: Note that I chose the wording "for everything" carefully. There are of course modules that specifically make use of Perl's reference counting and DESTROY to perform actions at the end of a scope, such as e.g. End or File::pushd (although note how careful the latter has to be not to clobber $@). So it is in theory possible to implement "auto close" behavior this way. However, I've already mentioned the major caveats to be considered, like accidental circular references, or in this case just accidentally storing a reference to the object somewhere else, will interrupt this mechanism. Because of these possible accidents I'd call it (for lack of a better term) less "theoretically reliable" than Java's try. So this is why I recommend against DESTROY for a generalized, idiomatic mechanism - but for situations where the scope is small and you can keep track of the references it may be applicable.

Replies are listed 'Best First'.
Re^2: Resource management (updated)
by pwagyi (Monk) on Oct 29, 2017 at 10:48 UTC
    So I guess manual management is the way to go. I’m not sure I should start a new post. Because I have related question with xs using swig. How does those swig code that call C Function (that allocates either some memory or other resources that needs to be destroyed) be dealt with? If there’s get_foo and delete_foo, one has to manually call delete_foo from Perl as well?

      pwagyi:

      No, that's not what was meant. Normally, you don't have to worry about it, because perl uses reference counting, rather than delayed garbage collector. So once the value is no longer accessible, it's automatically cleaned up. In this respect, perl is much more like C++ with RAII where you can just let the destructor handle cleanup for you. Like this:

      sub read_file { open my $FH, '<', 'FileName' or die $!; while (<$FH>) { ....process lines... } }

      If you don't store $FH in some persistent location, then once read_file returns, then 'FileName' is already closed, because $FH is no longer accessible.

      You need to be careful (i.e. manual management) only when you're persisting the variable:

      # Here we're at the top level of a script open my $FH, '<', 'FileName' or die $!; while (<$FH>) { ... process lines ... } # Now we're sleeping for 5000 seconds, and FileName is still open, bec +ause the program still # has $FH accessible. sleep 5000

      So don't put resources in global variables, and only use resources for the duration of a subroutine, and you'll rarely need to worry about it.

      For your XS stuff, you'll either have to manually manage the resource if it's coming from C, or you can make your code object oriented and let DESTROY handle it. If you present a bit more detail of your use case, you can get more specific advice.

      ...roboticus

      When your only tool is a hammer, all problems look like your thumb.