Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

Patching a Package (Scalar::Util)

by tall_man (Parson)
on Apr 19, 2006 at 16:35 UTC ( #544404=perlquestion: print w/replies, xml ) Need Help??

tall_man has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks, I have several scripts that I would like to be able to run on a variety of systems where I don't control the main installation directories. In particular, one of them is a perl 5.8.0 where the List::Util version is "1.07_00" and therefore refaddr is missing.

I tried creating my own override of the whole List::Util package, but the XS part was not portable to all systems.

Instead, to fill in the missing function, I created the following module:

package PatchPackages; use strict; use version; our $VERSION = qv/0.0.1/; sub import { require Scalar::Util; if (! Scalar::Util->can('refaddr')) { # Copied from more recent Scalar::Util code. # Makes up for this function being missing on some # of our 5.8.0 installations. *Scalar::Util::refaddr = sub ($) { my $pkg = ref($_[0]) or return undef; if (Scalar::Util::blessed($_[0])) { bless $_[0], 'Scalar::Util::Fake'; } else { $pkg = undef; } "$_[0]" =~ /0x(\w+)/; my $i = do { local $^W; hex $1 }; bless $_[0], $pkg if defined $pkg; $i; } } } 1;

This seems a little messy, but it works. Does anyone know of a cleaner way to do this?

Replies are listed 'Best First'.
Re: Patching a Package (Scalar::Util)
by ikegami (Pope) on Apr 19, 2006 at 17:26 UTC

    Why is all that stuff in import? That's wrong because it imposes the following two unnecessary restrictions:

    • The module must be loaded using use PatchPackages;. Using require PatchPackages; or use PatchPackages (); will not work, because import does not get executed in those circumstances.

    • use PatchPackages; can only appear once in your code. import is called every time use PatchPackages; is encountered.

    Put the code at the top level (as in the following snippet) to fix those problems. It will only be executed once, and it will get executed no matter how the module is loaded.

    package PatchPackages; use strict; use version; our $VERSION = qv/0.0.1/; require Scalar::Util; if (! Scalar::Util->can('refaddr')) { ... } 1;
Re: Patching a Package (Scalar::Util)
by dragonchild (Archbishop) on Apr 19, 2006 at 16:44 UTC
    That's about the best you're gonna get. I'd add it to the @EXPORT, @EXPORT_OK, and %EXPORT_TAGS, too. And, comment the f@#$ out of it.

    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
      Scalar::Util only exports refaddr by request, but your suggestion is good. I have added the following (within the if test):
      # Allow users of Scalar::Util to import the new symbol on request. push @Scalar::Util::EXPORT_OK,'refaddr';
Re: Patching a Package (Scalar::Util)
by xdg (Monsignor) on Apr 19, 2006 at 18:20 UTC

    In the category of evil workaround hacks, demerphq recently pointed out that Data::Dump::Streamer offers an independent reimplementation of refaddr. If you can get DDS to compile on those various systems, you should be in business.


    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: Patching a Package (Scalar::Util)
by ikegami (Pope) on Apr 19, 2006 at 17:37 UTC
    Quote version:
    An alternate way to create a new version object is through the exported qv() sub. This is not strictly like other q? operators (like qq, qw), in that the only delimiters supported are parentheses (or spaces).

    It's really just a function called qv, not a quote operator. Change
    qv($_ =~ /0.0.1/)
    so change it to one of the following:
    qv"0.0.1" (the space is optional for double quotes)
    qv '0.0.1' (the space is necessary for single quotes)
    qv q/0.0.1/

Re: Patching a Package (Scalar::Util)
by demerphq (Chancellor) on Apr 19, 2006 at 22:36 UTC

    Actually I dont get that patch exactly. If you are going to rebless into a non overloaded class name then refaddr becomes simply 0+$ref. I'm going to supply a patch to p5p. Anyway, I would take all of that out of the import method.


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://544404]
Approved by Corion
Front-paged by bart
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (6)
As of 2020-09-27 19:00 GMT
Find Nodes?
    Voting Booth?
    If at first I donít succeed, I Ö

    Results (142 votes). Check out past polls.