|There's more than one way to do things|
RFC: User subroutine hinting interface for autodieby pjf (Curate)
|on Mar 04, 2009 at 07:20 UTC||Need Help??|
G'day learned monks,
The bug all comes down to context, and how subroutines report failure, and is best shown with an example:
Our problem is that the copy subroutine always uses return 0; to indicate failure. In a scalar context this is false, and autodie assumes it means an error. However in a list context it returns (0) (a list of a single zero), which looks like something which may be a legitimate value, and so autodie passes it through fine. By default, autodie only thinks a failure has occured if it sees an empty-list, or a list consisting of a single undef.
As this example shows, autodie can fail to detect failure when it occurs in unexpected ways. The solution is to provide a hinting mechanism, where not only can a subroutine be made autodying, but hints can be provided to control to describe what it considers to be a failure.
To keep the autodie interface clean, and to ensure nobody has to repeat themselves, these hints are provided out-of-band. So when you see a piece of code like:
autodie will look up the hints table for File::Copy::copy and check to see which conditions indicate failure. A table of these hints for common modules will be included in the next autodie release, but they can also be supplimented by your own code (eg: use my::autodie::hints), or even built into exporting modules themselves. This all works right now on the hints branch of the source code repository.
Most of the time, end-users will never have to worry about the hinting interface, it's only something that myself, or module developers, or very eager people will be using. Having said that, I want to make sure I get it right.
Right now, the current hinting interface sucks. You have to do something like:
Note that we're OR'ing bits together manually to set the hints. That was due to an old idea that came to me on a coffee-deprived tram ride, and which didn't work out. Note that we're also including some big ugly constants just to use them in a single call. I don't like that at all.
So, I'd like to replace the interface. Currently the plan is to have something like this:
Here we're passing in a list of strings as hints, which makes error messages nicer (you typed X, did you mean Y?), and avoids having to screw around with bitwise operations. Settings currently have the first word being the context they apply to (scalar/list), and then we list what are considered 'failure' values. The current list are as follows:
Note that there are some things which are missing from the list, my goal is to have autodie work with the most common legacy ways of signalling errors, not every possible wacky scheme imaginable. Also note that the hinting mechanism will never be used for Perl's built-in functions, autodie is already aware of their special cases, and no further user intervention is necessary.
So, my question to you, dear monks, is can I do this better? Can the hints be given better names? Is my set_hints_for method particularly unintuitive? How would you expect this to work?
The autodie module is going into the 5.10.1 release of Perl, and as such if I screw things up, it's likely they'll stay screwed for a long time. Any comments, feedback, or questions are appreciated.
Perl Training Australia