Every now and again I see people on StackOverflow promote the use of autodie. But in the code here and elsewhere in the net I don't see autodie very often. Are there some disadvantages? Do I lose something when using autodie? (I have the idea of getting spoiled, when using autodie)
The autodie
documentation lists a couple of gotchas and bugs you should be aware of. However, most of those are relatively minor, and also fixable in the long run.
Other than that there are no real disadvantages, other than maybe the additional dependency when running on old perl versions. The fact that it isn't used very often yet might very well be caused by it being relatively new. Nevertheless, autodie
(and even the old Fatal
module) are generally a good idea.
autodie
to make one of non-builtins fatal, you'll have to either fully define it or pre-declare it first. That's not related to prototypes. The use-case for that are usually modules you have no control over, but that have the weird semantic of indicating failure by returning magic values. So all you have to do for those is load them before autodie. easy enough. For your own functions you can always just make it fail with a proper exception instead, or and possibly write a magic-retval wrapper around it, in case you have backward compatibility to consider. –
Aronson AUTOLOAD
is for methods, autodie
is for making functions fatal. –
Aronson use subs qw(foofunc barfunc);
does just that. Is that what you meant? Also my concern is whether other modules that you load might cause problems if they use autodie;
. Suppose I want to use modules A and B, and to autodie-ify f()
which is defined in B.pm. I write use A; use B; use autodie qw(f);
. But what if A.pm internally called use autodie;
, e.g. in its import()
? Does the world blow up? –
Manteau autodie
cannot be used with methods generally? (That seems like an arbitrary restriction.) Or just autoloaded methods? (Still undesirable, but somewhat understandable.) –
Manteau use subs ...
isn't usually needed to predeclare subs. You can use a sub declaration without a body. sub foo; ... later in the code ...; sub foo { ... }
–
Abomasum The technology is mostly fine, but it's action at a distance and magical. Some people who read only sections of the code might not understand what happens since autodie is far away from the code they inspect. Since not everyone uses it and it's only become a practice recently, I suspect most people don't expect it. It's not really a big deal, but that sort of thing always seems ugly to me.
There is a language model that follow C's function-based paradigm where all functions return a value, and it's up to the user to check for the return value. Perl is in this group. If I call a function, it is my responsibility to check whether or not that function actually returned something useful.
There is another language model that follows Java's exception-based paradigm where functions that fail return exceptions, and if the user needs to handle the exception, they must explicitly handle the exception. Most modern languages written since Java follow this exception-based approach.
Newer languages are exception-based because it handles the lazy developer problem. In C style programming languages, if a developer forgets or doesn't bother to check the exit status of a function, the program continues. In Java style programming languages, the program dies. In both cases, a developer could handle the problem of an invalid function result, it's that exception-based languages force developers to do so.
Why don't you see use autodie
here? Several theories:
It's New
The autodie
pragma is fairly new, and most developers don't have a good way to incorporate new knowledge in their Perl programming. For example, say
has been around since 5.10, but I still see few developers use it even though it's a big improvement over print
, and is simple to use. If a developer doesn't learn autodie
when they initially learn Perl, they probably won't ever know about it.
There's No Try/Catch Syntax in Perl
Here's how Perl generally works:
open $fh, "<", $file;
if ( not defined $fh ) {
... # What I do if `$fh` didn't get set.
}
I check the value of $fh
after my open
statement (Okay, generally you check the return value of open
itself and not the opened $fh
, but bear with me!). The syntax is fairly simple and clean. It's easy to understand.
What if you used autodie
and took an exception based approach? There's no built in try/catch
statement in Perl like there is in Java. Instead, you take a semi-clumsy way of using eval
:
use autodie;
my $fh; # Got to be declared outside of the eval
eval {
open $fh, "<", $file;
}; # Don't forget that semicolon!
if ( $@ ) {
... # What I do if function "foo" doesn't return a good value...
}
Can you say yucky? I knew you could! Because $fh
is lexically scoped, I have to declare it before my eval
. Plus, I'm not even getting into the whole issue of $@
being a globally scoped variable!
It's Way Incomplete
Most modules and built in functions don't work with autodie
which is more or less limited to IO calls, fork
, system
, and exec
, Even here, it's incomplete: print
and flock
don't work with autodie
. Outside of these, no other Perl builtin function work with autodie
. Popping values off an empty array doesn't force my program to croak. Few modules check the status of autodie
to see whether their functions or methods should croak
instead of returning false values. So, the whole idea of turning Perl into an exception-based language doesn't happen.
Even places where you think autodie
would work just don't. If you use File::Copy
to get the copy
and move
commands, don't depend upon autodie
to catch a bad file copy. You still need to check the return value of copy
. If you use File::IO
, all bets with autodie
are off.
So, autodie
doesn't quite live up to its bold promise of turning Perl into a more exception based programming language. For most people, it's mainly catches open
statements, and most developers don't have issues with open ... or die...
.
I like the exception based approach to development, and I believe that all modules should croak on error by default. Force developers to handle exceptions instead of ignoring them. I write my modules and functions to croak when there are problems, and use eval
to handle exceptions. Unfortunately, autodie
just doesn't do a whole lot right now.
One other consideration is that autodie and utf8::all didn't play nicely together until a recent release of utf8::all. utf8::all is another convenience module that, like autodie, helps to setup Perl to do common tasks (this time unicode) automatically.
© 2022 - 2024 — McMap. All rights reserved.
autodie
must be declared before any call touse autodie;
Seems to suggest you must declare (does that mean prototype?) any subs you want to use beforeuse
ing any module, since that module may internallyuse autodie;
-- any thoughts? Also wondering about interactions with AUTOLOAD. – Manteau