Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

How to convert a symbolic reference to a hard reference

by princepawn (Parson)
on Nov 06, 2003 at 00:10 UTC ( [id://304908]=perlquestion: print w/replies, xml ) Need Help??

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

I am reading in a configuration file which has a string representing the package-qualified name of a DBI exception handler.

DBI does not accept symbolic references for its HandleError attribute and that is what this string is intended to handle.

Therefore, I must give DBI a hard reference and would like to know the most direct way of doing so. Below almost works, but I get a funny error message in my dummy example.

the general idea

*Config::DBI::error_handler = eval "&$symbolic_ref"; DBI->connect($DSN, $User, $Pass, { HandleError => Config::DBI::error_handler } );

the dummy code

package M; sub x { print "sub __PACKAGE__x"; } sub y { print "sub __PACKAGE__y"; } 1; package N; $s = 'M::y'; *M::x = eval "&$s"; M::x();

but it gives a bizarre errmsg:

~/hacks/config-dbi/scripts $ perl symref.pl Undefined subroutine &main::1 called at symref.pl line 19. sub __PACKAGE__y ~/hacks/config-dbi/scripts $

Replies are listed 'Best First'.
Re: How to convert a symbolic reference to a hard reference
by broquaint (Abbot) on Nov 06, 2003 at 00:19 UTC
    Creating symbolic references to a subroutine is fine, just not accessing them symbolically e.g
    use strict; sub foo { print "in foo(@_)"; } my $f = \&{"foo"}; $f->("var"); ## or more succinctly (\&{"foo"})->("temp"); __output__ in foo(var) in foo(temp)
    And the bizarre error is due to eval trying to execute the return of M::y(), which is the return value of print.
    HTH

    _________
    broquaint

Re: How to convert a symbolic reference to a hard reference
by blokhead (Monsignor) on Nov 06, 2003 at 00:18 UTC
    Close. &x does not return a reference to the subroutine at x, it returns the result of that subroutine (ignoring prototypes and passing along @_). For a reference, you need \&x. Changing
    *M::x = eval "&$s";
    to this
    *M::x = eval "\\&$s";
    causes your dummy code to work as expected.

    blokhead

Re: How to convert a symbolic reference to a hard reference
by revdiablo (Prior) on Nov 06, 2003 at 00:47 UTC

    I see your question has been answered directly by a few other fine Monks, but I thought I might add something. If you'd like to get a coderef without using eval, you can use can. For example:

    sub foo { print "Foo!\n"; } my $pkg = "main"; my $sub = "foo"; my $cr = $pkg->can($sub) or die "Can't find '$sub' in package '$pkg'\n"; $cr->();
      Very nice, thanks. You don't even have to split the package off:
      $sub = "X::foo"; $cr = main::->can($sub);
      You can just use any existing package name. (I say main:: instead of main-> in case there is a &main sub.)

      If you are downvoting this for other than lack of interest, thanks for sending me a message or reply to let me know why so I can do better (or just stay quiet) next time.

Re: How to convert a symbolic reference to a hard reference
by ysth (Canon) on Nov 06, 2003 at 00:26 UTC
    Your eval "&$s" creates a call to the sub, not a reference to it. The return from the sub is the return value of the print (which is 1 because the print succeeded).

    Try eval "\\&$s" instead, or avoid the eval altogether with *M:x = do{ no strict 'refs'; \&$s }

    If you are downvoting this for other than lack of interest, thanks for sending me a message or reply to let me know why so I can do better (or just stay quiet) next time.

Re: How to convert a symbolic reference to a hard reference
by Roger (Parson) on Nov 06, 2003 at 00:28 UTC
    Perhaps the simplest fix would be to change the & to *.
    *M::x = eval "&$s";
    change to
    *M::x = eval "*$s";
Re: How to convert a symbolic reference to a hard reference
by Anonymous Monk on Nov 06, 2003 at 14:28 UTC
    This should work just fine.
    HandleError => \&$symbolic_ref

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (6)
As of 2024-04-19 18:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found