Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options

Re^2: Exported subroutine redefine

by ribasushi (Pilgrim)
on Nov 10, 2007 at 19:17 UTC ( [id://650078] : note . print w/replies, xml ) Need Help??

in reply to Re: Exported subroutine redefine
in thread Exported subroutine redefine

Thanks for answering, this sounds like a good idea. Can you tell me how can I get a list of all currently populated namespaces? %INC contains only namespaces tied to a physical .pm file, and if a file has several package X pragmas I will examine only the first one.

Btw if you are curious the ickyness comes form the fact that I am fooling around with exception handling, and I had this nice idea of globally redefining Carp::croak() and Carp::confess() to throw an object except of a string (I know I know it is far from best practice to fool around with core modules, but I really liked the idea, an wanted to see if it can actually work). Since Carp is a very central module it is being used all over the place in many other modules, and hence it is
1) impractical to change all calls to it Carp::x()
2) impractical to attempt to load my exception handler before any references to Carp.
The two subroutines that must be redefined are trivial one-liners, thus I figured it should do no harm:
sub croak { die shortmess @_ } sub confess { die longmess @_ }

Addition: Why I don't simply overload CORE::die? Because for one it can be overloaded by someone else, and more importantly module authors sometimes examine $@ and finding an object there has a very remote chance of breaking stuff (although I have backwards compatible stringification of '<error> at <file> line <ln>.' On the other hand croak is clearly designed to be seen by the user, who in this case will be expecting an object.

Replies are listed 'Best First'.
Re^3: Exported subroutine redefine
by tilly (Archbishop) on Nov 11, 2007 at 03:33 UTC
    In the case of Carp specifically there is a far easier way. Use Carp::Heavy. Then redefine Carp::longmess_heavy and Carp::shortmess_heavy.

    Otherwise you'd have to walk the symbol table. Just to get you started on that, print out the keys of %main::. All of the keys ending in :: are subtables you can look for. Beware of infinite loops. (For instance %main::main::main:: is the same as %main::.)

Re^3: Exported subroutine redefine
by Somni (Friar) on Nov 11, 2007 at 02:29 UTC
    Strange, why aren't you just setting up your own $SIG{__DIE__} handler? It seems tailor-made to solve your problem for you. Granted, it's a hack, and can get messy, but it's a far better hack than trying to overload another module's subroutines globally.

    A long time back I went down this road, as well. I thought it was a great idea to setup a __DIE__ handler and catch all the errors, turning them into pretty output for a web framework I was designing. I suppose it worked, sorta. It's much cleaner to design an actual exception model, with exception classes thrown by code, and possibly a catch routine that can transform string exceptions into a relevant object.

    If the object in $@ has stringification it shouldn't break anything that's attempting to match against it. The only thing it should "break" is something that's checking to see if it's an object, in which case that code should know what it's doing.

      Because $SIG{__DIE__} is too often used by other packages as well. I think my final solution is cleaner in regards to what I want to do.
Re^3: Exported subroutine redefine
by educated_foo (Vicar) on Nov 10, 2007 at 20:03 UTC
    Could you just redefine Carp::shortmess and Carp::longmess? If not, you can walk the symbol table starting with something like this:
    for (grep /(?<!main)::/, keys %::) { # do stuff... }