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

I'm wondering if there's a better way to avoid the warning of "Ambiguous use of X resolved to Y".
Here's what I did:
# issues "Ambiguous use of X resolved to Y" warning that # I don't know how to turn off, these don't work: # $SIG{__WARN__} = sub{} # $^W = 0 # no strict 'refs' my $old_scan_podpath = *{Pod::Html::scan_podpath}{CODE};
I couldn't get rid of the warning generated from that line of code, so I went with this:
# issues "Subroutine X redefined at Y" warning, but # I can turn that one off with $^W local( $^W ) = 0; # Needed because I'm using a symbolic ref now. no strict 'refs'; my $old_scan_podpath = *{'Pod::Html::scan_podpath'}{CODE};
That seems to work.

After that's set up, I can do this:
local(*Pod::Html::scan_podpath) = sub { # do stuff here # call the old implementation &$old_scan_podpath; # uses @_ };
And yes, I'm aware of a few wrap modules out there, but for some reason I didn't want to add more dependencies to this script than I already have. Besides, it seemed like a good opportunity for me to learn how to do this.

So, am I avoiding that warning the right way? Or is there a better way?

Thanks!
-Dave

Replies are listed 'Best First'.
Re: Ambiguous use of X resolved to Y
by chromatic (Archbishop) on Feb 05, 2004 at 23:28 UTC

    I believe you're running into magic autodisambiguation of hash keys versus non-words. In short, the first example is also a symbolic reference. It's just not in quotes, which makes it hard for Perl to tell whether you want it to be a quoted string (since it contains non-identifier characters) or you want to use the result of a function call as the hash key.

    Wow, that's an unclear paragraph.

    I seem to recall that just taking a reference to the function doesn't quite do the right thing when local is involved, but I'd try my $old_sub = \&Pod::Html::scan_podpath; first. Hook::LexWrap is definitely a better general choice, though.

Re: Ambiguous use of X resolved to Y
by diotalevi (Canon) on Feb 05, 2004 at 23:30 UTC
    my $old = \&Pod::HTML::scan_podpath; { local $^W; *Pod::HTML::scan_podpath = sub { &{$old}( @_ ); }; }
      I seem to recall trying an incantation very similiar to that, but it ended up causing deep recursion. It seemed that the *{name}{CODE} syntax was required to make it work right.

      I suspect that what happens, is that a reference to the actual function in the module is lost when the glob gets reassigned. The reference held in $old is to a glob, and calling a function on it essentially references *{$old}{CODE}, which isn't really what you wanted (because it's the new one). That causes recursion.

      If I'm understanding that wrong, someone please correct me.

      -Dave
        That could happen if the function didn't already exist before you took a reference from it. Be sure to have loaded the code for that function before you run that snippet. Consider also checking for recursion:
        my $old = \&Pod::HTML::scan_podpath; { local $^W; *Pod::HTML::scan_podpath = sub { if ( $old == \&Pod::HTML::scan_podpath ) { croak "..."; } &{$old}( @_ ); }; }