There is always a problem when one employs too much black magic. But what if you're not actually writing it, but merely useing it?

From what I gather around here, there are a couple of highly-recommended modules to use: Contextual::Return (which is severely simplifying some of my code, so a ++ there) and Exception::Class. Both of these have significant amounts of magic in them, with CR having more when it's trying to fake out caller for intuitive tracebacks, especially when wondering what is going on:

VALUE { confess "What the... use this as a hashref, bub!" }
(that should never happen, gotta figure out how to tell Devel::Cover that, but I digress. Probably will just never get 100% and be ok with that.) However, what is giving me a minor amount of trouble is actually the both of these together. Well, not quite. It's testing. When I want to test my exceptions, it simply makes sense (to me, at least) to abuse someone else's shortcuts. So I load in Test::Exception to my test:
use Test::More qw(no_plan); # yeah, yeah - I'm developing it. I'll co +unt later. use Test::Exception; BEGIN { use_ok("My::Module"); }
Now, remember, My::Module in turn has use Contextual::Return in there as the first use (after strict and warnings). At this point, I get an error message:
t/get_set..............Prototype mismatch: sub CORE::GLOBAL::caller (; +$) vs none at /usr/lib64/perl5/site_perl/5.8.8/Contextual/Return.pm l +ine 12.
Kind of annoying. After a bit of playing, I've not come up with a better solution than simply moving the Test::Exception load to after the use_ok of my module. Apparently, Test::Exception has some black magic that mucks about with Contextual::Return's black magic. Actually, I expect it's actually Sub::Uplevel, which is dragged in by TE.

Though I'm hopeful that much of this deep black magic can go away in perl 6, I have to wonder - will we get back to this level again before perl 7? Is this convenience-creep inevitable that we'll play with things that can come back to nibble at our heels (if not outright bite us in the arse)?

Update: Not that the problem is the main point, but I am running the latest Test::Exception and Sub::Uplevel versions. Mind you, that brings up a parallel question: who to report it to? Is it a problem in C::R? Or in S::U? I suppose I was assuming that this type of dark magic merely gets in the way - if one person does it, it works fine, but when you get competing implementations, that's when things go awry.

Update 2: From looking at S::U's perldoc, it appears there's a conscious effort there to work with C::R. Perhaps it's just C::R's need to work with S::U that is required (for when the loading is in the reverse order). Apparently such bug reports exist, and now we get back into a recent topic about abandoned modules... ;-)

Replies are listed 'Best First'.
Re: Too much black magic
by xdg (Monsignor) on Jul 05, 2008 at 12:23 UTC

    Sub::Uplevel installs a CORE::GLOBAL::caller subroutine with a prototype that matches CORE::caller. Contextual::Return's CORE::GLOBAL::caller replacement has no prototype -- which is what causes the error if Contextual::Return loads after Sub::Uplevel.

    I suspect you could load just Contextual::Return instead of your entire module before Test::Exception and it would work -- I guess replacing an unprototyped function with a prototyped one is not considered an error.

    In my view, it's a bug in Contextual::Return, since you want to have the same caller() semantics as without a CORE::GLOBAL::caller override.

    my $caller = caller @foo; # like "scalar @foo"

    Yes, prototypes are evil, but core functions do have them, so CORE::GLOBAL replacements should have them as well for consistency.

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: Too much black magic
by starbolin (Hermit) on Jul 06, 2008 at 01:07 UTC

    Unfortunately the problem is not unique to your situation nor to only C::R and S::U. There probably isn't a perl programmer who hasn't struggled with omissions in one or more modules. On a larger scale, any engineer struggles with interoperability of parts.

    In my life as an EE I made daily decisions such as: "A and B don't work together, do I, keep A and abandon B, keep B and abandon A, or do I modify the circuit to establish de-coupling between the parts." The most important criteria often lay in whether the respective vendors were co-operative in resolving problems. This co-operation, unfortunately, usually depended on the size of our business with the vendor.

    Experienced designers knew, if you designed too many wis-bang parts into the design, these interdependencies would kill your project, or your health. So we had rules to avoid this situation. "Use only parts with multiple sources." "Don't use 'wis-bang' parts." "Avoid 'single-product' vendors." and important for the OP "Use only one 'wis-bang' part per design and surround it with 'jelly-bean' parts. The idea behind these was to prefer parts that had cross-licenses agreement between vendors and thus a stable interface specification. It also assured that vendors were competing on price and reputation, thus ensuring their interest in interoperability. The last rule ensured that problems were isolated to one vendor with which you, hopefully, had some clout.

    FOSS has only a loose coupling between vendor and customer. The writer of a module often has no financial interest in the success of his code. Thus we rely exclusively on reputation to encourage vendor interest. ( And that's not a very big stick. )

    The conclusion to all of this is that we have little control over the interoperability of the modules we choose. Including multiple modules without research and testing will assuredly result in interoperability problems. We need to choose carefully and to shun modules that are too tightly coupled to the core or too each other. We have to choose modules with responsive authors and/or large user bases. Authors here often admonish us to "Don't reinvent the wheel." This is good advice but there is also a valid need for decoupling pulling us in the other direction. We need to also admonish others to: "Pick only tested modules with proven track records." "Use only one 'wis-bang' module per design." "Check for and avoid close module coupling." "Avoid modules from unresponsive authors."

    I know these assertions are going to get me into trouble, web forums having a low tolerance for assertions, but I think we need to promote some standard cautions to temper the standard "Don't reinvent the wheel." admonition.


    s//----->\t/;$~="JAPH";s//\r<$~~/;{s|~$~-|-~$~|||s |-$~~|$~~-|||s,<$~~,<~$~,,s,~$~>,$~~>,, $|=1,select$,,$,,$,,1e-1;print;redo}
Re: Too much black magic
by Anonymous Monk on Jul 05, 2008 at 03:37 UTC
    Maybe you need to upgrade
    0.27 - Patch to fix my broken code with the now working Sub::Uplevel. + Many thanks to David Golden
    I'm sure the authors would like know in either case