Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Take reference and then dereference die() and warn()

by dmitri (Curate)
on Nov 07, 2013 at 21:27 UTC ( #1061628=perlquestion: print w/ replies, xml ) Need Help??
dmitri has asked for the wisdom of the Perl Monks concerning the following question:

Friends,

Perhaps I have been away from Perl for too long, but the following problem has me baffled. I would like to die or warn depending on a setting. The following does not work:

if ($error) { ($die_on_error ? \&die : \&warn)->($error); }
This gives me Undefined subroutine &main::die called.... Neither can I successfully reference CORE::die or CORE::GLOBAL::die.

I have two questions:

  1. How do I take a reference to die?
  2. Is there a common Perl idiom to do what I want?

Thanks!

UPDATE: My perl is 5.10.1

Comment on Take reference and then dereference die() and warn()
Download Code
Re: Take reference and then dereference die() and warn()
by choroba (Abbot) on Nov 07, 2013 at 21:47 UTC
    The following works for me in 5.16.0:
    ($die_on_error ? \&CORE::die : \&CORE::warn)->($error);

    In 5.10.1, though, I am getting

    Undefined subroutine &CORE::warn called

    In older versions of Perl, you can still define your own subroutines and reference them (they can even be anonymous):

    ($die_on_error ? sub { die shift } : sub { warn shift } )->($error);

    I do not find it more readable than

    die $error if $die_on_error; warn $error;
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
      Thanks! I forgot to specify perl version, it's updated now. It's good to know it works in later perls.
Re: Take reference and then dereference die() and warn()
by tobyink (Abbot) on Nov 07, 2013 at 22:43 UTC

    It doesn't work because die and warn are keywords rather than subs in your namespace. As choroba has noted, in more recent versions of Perl many keywords are also available as functions in the CORE package, but the CORE package can behave abnormally sometimes.

    Carp usually gives more helpful line numbers than die/warn, and as a bonus, these are real functions:

    use Carp; ($die_on_error ? \&croak : \&carp)->($error);

    That said, I'm really quite liking this as an alternative:

    package My::Module; use warnings::register; ...; warnings::warnif("The flooble has become discombobulated!"); ...;

    The awesome thing about it is that people using your module can enable this warning like this:

    use warnings 'Your::Module';

    And if they'd prefer the warning to be fatal:

    use warnings FATAL => 'Your::Module';

    ... and everything works just like Perl's built-in warnings categories! Yay!

    (Though I'll note that the Perl 5.8 implementation of custom warnings categories kinda sucked. It's been good since 5.10.0.)

    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
Re: Take reference and then dereference die() and warn()
by Laurent_R (Parson) on Nov 08, 2013 at 00:07 UTC

    Sorry, I might have missed something, but why would you need reference to die in the first place?

    Can't you have simply something like this:

    if ($error) { $die_on_error ? die : warn->($error); }
    I guess it should work fine.

    If not in your case, you could define a "my_die" function:

    sub my_die{die "I died\d"}
    and take a reference to my_die, or alternatively make it a coderef with something like this:
    $my_die = sub {die};

      The reason is that I want to put this into the or:
      do_something() or ($die_on_error ? \&die : \&warn)->("error");

        But you simply don't need that: you can just die or warn in the usual way within your ternary operator, as you can see in the following Perl one-liners:

        $ perl -e '$die_on_err=shift; 0 or ($die_on_err? die "failed\n" : warn + "warning\n")' 1 failed $ perl -e '$die_on_err=shift; 0 or ($die_on_err? die "failed\n" : warn + "warning\n")' 0 warning

Re: Take reference and then dereference die() and warn()
by Jenda (Abbot) on Nov 08, 2013 at 17:37 UTC
    sub report { if ($die_on_error) { die $_[0]; } else { warn $_[0]; } } ... report($error) if ($error);

    I don't think you want to have to type all that nonsense every time you need to report an error.

    Jenda
    Enoch was right!
    Enjoy the last years of Rome.

Re: Take reference and then dereference die() and warn()
by Beechbone (Pilgrim) on Nov 12, 2013 at 13:56 UTC
    $SIG{'__WARN__'} = sub { die @_ } if $die_on_error; warn "foooooo";

    Does not quite work if you allow your code to spit out warnings for other reasons. In that case, you have to tag your speacial warnings, e.g.:

    $SIG{'__WARN__'} = sub { die @{$_[0]} if ref $_[0] eq 'ARRAY'; warn @_ +; } if $die_on_error; warn "foooooo"; # never dies warn ["foooooo"]; # sometimes dies

    Search, Ask, Know

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1061628]
Approved by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (7)
As of 2014-08-28 06:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (257 votes), past polls