Overriding a require'd module's subroutine

Discussion in 'Perl Misc' started by Ratty, Apr 27, 2010.

  1. Ratty

    Ratty Guest

    I'm using the MARC::Batch module. It refuses to process records with
    character encoding issues. It dies with a warning about line 166 in
    Encode.pm. I can use eval to make it skip bad records instead but I
    don't want that either. I want it to do the best it can. What I need
    to do is modify Encode::decode so it does not die when it can't decode
    a string. This works if I add an eval to Encode.pm sitting in my perl/
    lib directory. But I don't want to do it this way. I want everything
    restricted to my one calling program. I seem to remember doing
    something similar years ago by simply copying the subroutine, with
    package name, into my program and my program would use that instead.
    But it doesn't work for me this time. No errors, it simply ignores it.
    Perhaps because I'm not calling the module directly this time, but
    rather it is being called somewhere in the bowels of MARC::Record,
    which I'm also not calling directly.

    use MARC::Batch;

    ## Programming here

    ## Attempt to override
    sub Encode::decode($$;$)
    {
    my ($name,$octets,$check) = @_;
    return undef unless defined $octets;
    $octets .= '' if ref $octets;
    $check ||=0;
    my $enc = find_encoding($name);
    unless(defined $enc){
    require Carp;
    Carp::croak("Unknown encoding '$name'");
    }
    ## Add eval heres
    my $string;
    eval { $string = $enc->decode($octets,$check); };
    $_[1] = $octets if $check and !($check & LEAVE_SRC());
    return $string;
    }

    What's the most elegant way to redefine somebody else's subroutine?
    BTW, I also tried:

    {
    local *Encode::decode = \&myDecode;
    }

    Doesn't work either
     
    Ratty, Apr 27, 2010
    #1
    1. Advertising

  2. Ratty

    Ratty Guest

    On Apr 29, 10:23 am, "Mumia W." <paduille.4061.mumia.w
    > wrote:
    > On 04/27/2010 03:47 PM, Ratty wrote:
    >
    >
    >
    > > I'm using the MARC::Batch module. It refuses to process records with
    > > character encoding issues. It dies with a warning about line 166 in
    > > Encode.pm. I can use eval to make it skip bad records instead but I
    > > don't want that either. I want it to do the best it can. What I need
    > > to do is modify Encode::decode so it does not die when it can't decode
    > > a string. This works if I add an eval to Encode.pm sitting in my perl/
    > > lib directory. But I don't want to do it this way. I want everything
    > > restricted to my one calling program. I seem to remember doing
    > > something similar years ago by simply copying the subroutine, with
    > > package name, into my program and my program would use that instead.
    > > But it doesn't work for me this time. No errors, it simply ignores it.
    > > Perhaps because I'm not calling the module directly this time, but
    > > rather it is being called somewhere in the bowels of MARC::Record,
    > > which I'm also not calling directly.

    >
    > > use MARC::Batch;

    >
    > > ## Programming here

    >
    > > ## Attempt to override
    > > sub Encode::decode($$;$)
    > > {
    > >     my ($name,$octets,$check) = @_;
    > >     return undef unless defined $octets;
    > >     $octets .= '' if ref $octets;
    > >     $check ||=0;
    > >     my $enc = find_encoding($name);
    > >     unless(defined $enc){
    > >    require Carp;
    > >    Carp::croak("Unknown encoding '$name'");
    > >     }
    > >     ## Add eval heres
    > >     my $string;
    > >     eval { $string = $enc->decode($octets,$check); };
    > >     $_[1] = $octets if $check and !($check & LEAVE_SRC());
    > >     return $string;
    > > }

    >
    > > What's the most elegant way to redefine somebody else's subroutine?
    > > BTW, I also tried:

    >
    > > {
    > > local *Encode::decode = \&myDecode;
    > > }

    >
    > > Doesn't work either

    >
    > I can't see why that doesn't work, but I suggest placing your new
    > Encode::decode before the use statement for MARC::Batch. Perhaps
    > MARC::Batch stores a reference to the subroutine.


    OK, got it to work - don't understand why though.

    I tried just pasting the entire contents of Encode.pm on to the end
    of my program and that worked. Then I started removing things until it
    stopped. Found out it requires a use statement in there. As in:

    package Encode;

    use Encode::Alias;

    sub decode($$;$)
    {
    my ($name,$octets,$check) = @_;
    my $altstring = $octets;
    return undef unless defined $octets;
    $octets .= '' if ref $octets;
    $check ||=0;
    my $enc = find_encoding($name);
    unless(defined $enc){
    require Carp;
    Carp::croak("Unknown encoding '$name'");
    }
    my $string;
    eval { $string = $enc->decode($octets,$check); };
    $_[1] = $octets if $check and !($check & LEAVE_SRC());
    if ($@) {
    return $altstring;
    } else {
    return $string;
    }
    }

    Doesn't work without it. I wonder why.
     
    Ratty, May 1, 2010
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Amit

    Calling subroutine in fortran module

    Amit, Jan 30, 2005, in forum: C Programming
    Replies:
    5
    Views:
    1,667
    Dave Thompson
    Feb 7, 2005
  2. Replies:
    10
    Views:
    292
    Gunnar Hjalmarsson
    Aug 11, 2005
  3. Mark Mackey
    Replies:
    8
    Views:
    134
    Anno Siegel
    Feb 9, 2006
  4. king
    Replies:
    5
    Views:
    202
  5. Replies:
    3
    Views:
    129
    Tad J McClellan
    Mar 21, 2009
Loading...

Share This Page