7

The autodie documentation hints that it is possible to use it for other functions than those built-ins which it can handle by default, but there are no clear examples how to do that in it.

Specifically I would like to use it for the Imager module. A lot of the functions and methods of that can fail, and I would prefer if that wouldn't mean that my code will be littered with or die Imager|$image->errstr; phrases all over.

Of course, if there's another way than using autodie to achieve that, I would be interested in that too.

pjf
  • 5,993
  • 25
  • 42
Rörd
  • 6,556
  • 21
  • 27

3 Answers3

4

autodie only works with functions, not methods. This is because it's lexically scoped, and method lookup can't be lexically scoped. autodie::hints explains how to tell autodie about user-defined functions, but that won't do anything for methods.

I don't know of any way to get autodie-like behavior for methods, unless the module has that built in (e.g. DBI's RaiseError).

You could have a subroutine to do the check, but it wouldn't save all that much code, since you'd still have to pass it the correct object or class to call errstr on.

cjm
  • 61,471
  • 9
  • 126
  • 175
2

See autodie::hints

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • Thanks. If I understood that correctly, I just need to put the names of the functions into the argument list for `use autodie` if they signal failure by one of the default behaviours listed in the introduction. But it still doesn't seem to work. Imager is mostly OO. Is there anything special I have to do to make autodie work with methods? – Rörd Mar 17 '11 at 15:00
1

Here is an alternative technique that works with methods:

package SafeCall;
    use Carp ();
    sub AUTOLOAD {
        my ($method) = our $AUTOLOAD =~ /([^:']+)$/;   #'

        unshift @_, my $obj = ${shift @_};

        my $code = $obj->can($method)
            or Carp::croak "no method '$method' on $obj";

        &$code or Carp::croak $obj->can('errstr')
                              ? $obj->errstr
                              : "calling $method on $obj failed"
    }

And to use it:

package Image;
    sub new {bless {here => 'ok', also => 'can be looked up'}};
    sub fails    {$_[0]{not_here}}
    sub succeeds {$_[0]{here}}
    sub lookup   {$_[0]{$_[1]}}
    sub errstr   {'an error occurred'}

package main;
use 5.010; # for say()

my $safe = sub {bless \$_[0] => 'SafeCall'}; 
# storing the constructor in the scalar $safe allows $safe to be used
# as a method:  $obj->$safe->method

my $img = Image->new;

say $img->$safe->succeeds;       # prints 'ok'

say $safe->($img)->succeeds;     # or call this way (also prints 'ok')

say $img->$safe->lookup('also'); # prints 'can be looked up'

say $img->$safe->fails;      # dies with 'an error occurred at file.pl line ##'
Eric Strom
  • 39,821
  • 2
  • 80
  • 152