Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Re: Re (tilly) 2: passing subroutine arguments directly into a hash

by demerphq (Chancellor)
on Oct 21, 2001 at 04:47 UTC ( [id://120335]=note: print w/replies, xml ) Need Help??


in reply to Re (tilly) 2: passing subroutine arguments directly into a hash
in thread passing subroutine arguments directly into a hash

Nice. I agree with you in that its difficult to do this stuff elegantly, and this is a decent solution. One minor thought though is that you might want to use the poorly documented
local $Carp::CarpLevel=1;
before your confess calls to make them appear from the correct perspective. Other than that looks good and might get borrowed (if you dont mind...)

Yves
--
You are not ready to use symrefs unless you already know why they are bad. -- tadmc (CLPM)

Replies are listed 'Best First'.
Re (tilly) 4: passing subroutine arguments directly into a hash
by tilly (Archbishop) on Oct 21, 2001 at 05:29 UTC
    Never.

    Manipulating $Carp::CarpLevel would be a bad idea normally simply because $Carp::CarpLevel is an internal interface that is not intended to be used outside of the core. But it gets worse.

    $Carp::CarpLevel is simply a horrible hack. I refuse to use it. In fact getting rid of mistakes in Exporter that were caused by misunderstandings of how $Carp::CarpLevel works was important enough for me to decide to rewrite Carp. And I did the rewrite with a much saner alternative, and I was going to proceed and kill $Carp::CarpLevel entirely.

    That was a project that I decided to give up on once I realized that the warnings pragma had likewise gotten it totally wrong internally, and I was not up to reversing it and correcting the misunderstandings. (Incidentally virtually everywhere where it was used, I found that it was misunderstood.) So for the indefinite future $Carp::CarpLevel is likely to remain an undocumented internal interface which is deprecated. And if someone else gets irritated with the fact that warnings will sometimes skip a ton of levels that it shouldn't skip, and turn a croak into a confess coming from the guts of the internals, it could easily go away.

    Therefore I strongly think that it should not be used. Ever.

    Incidentally a case in point for why the internal hackery is such a bad design. In the above, your game with the carp level just broke anyone else trying to play with it. The right way if you wanted to do it is to do:

    local $Carp::CarpLevel = $Carp::CarpLevel + 1;
    Of course this only works if you are going to confess or cluck at the end. If you are going to carp or croak, you will be so outta luck because it doesn't work anything like you would predict.

    Incidentally in Perl 5.8 the right way to achieve the effect that you want will be to export the functions from a module, and in that module do:

    $Carp::Ignore{ __PACKAGE__ } = 1;
    Which tells the rewritten Carp that the current package is one which it should not start a stack backtrace from. :-(I don't remember if I left this documented or not. I really should wrap that project up a bit better.)-:
      Whooo. Well that told me. :-) Heh.

      Good point about incrementing the carplevel instead of setting it, that would be a more clever way to go about it.

      But im a little confused about your other comments. Maybe a post to meditations about what you've found out? I for one would appreciate it, especially as I have used carplevel a number of times with good results (or else I wouldnt have brought it up eh?). I understand from gschwern that there is a new version (written by you perhaps?) of Carp expected for 5.7 (or something) that corrects at least one bug in it that I know of (that being the fact that when overloading stringify in objects it will use this stringification instead of printing the underlying string value of the reference, which can cause big problems (sometimes deep recursion).

      Nonetheless these are the type of things that I would really like to see a meditation on, so if you've got a few minutes... :-)

      Its funny though but I was just working on some code that does something similar in Benchmark. Benchmark wants to know its original callers package so that it can run its benchmarks inside of that lexical space. As I have rewritten Benchmark in an OO form the routine is no longer at the same depth in the call stack, nor is it called in the same way, and it will be being from various subclasses with their own call stack issues, accordingly I had to hack the routine to ignore any packages in the Benchmark heirarchy. Wasn't my preferred solution and makes me think that maybe this type of 'figure out the outside caller' routine needs to be carefully coded in a reusable form. In fact on that line, I would be willing to put some effort into that if you have some code or ideas to contribute. ...oO(Hmm, maybe a meditation in of itself)

      Yves
      --
      You are not ready to use symrefs unless you already know why they are bad. -- tadmc (CLPM)

        Well I am hoping that few enough here know about CarpLevel to make telling them not to use it counter-productive. (Hey, what is that? Perhaps I can find a use for that even though tilly dislikes it...?)

        As for an explanation of what I dislike, try this email and this followup.

        As for finding your parents caller out of your own hierarchy, take a look in the current development snapshot at the implementation of Carp::Heavy. It solves that exact problem fairly efficiently.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://120335]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (4)
As of 2024-03-29 09:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found