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

Okay, a little code sample
package base; sub function { } package derived; our @ISA = qw|base|; package main; derived->function(); # <-- works, not what I want my $pack = "base"; &{"${pack}::functon"}(); # <-- works, not what I want $pack = "derived"; &{"${pack}::function"}(); # <-- doesn't work, this is what I want $pack = "derived"; eval "${pack}->function()"; # <-- works, not what I want
Hopefully thats pretty self-explanatory. Basically, I want to invoke a package-level method (no objects or blessed references) with inheritance, where I do not know the name of the base class to invoke upon at compile time, but I have it in a scalar at run time. Further, I would like to avoid the use of "eval" if at all possible.

Replies are listed 'Best First'.
Re: symbolic reference + inheritance
by almut (Canon) on Sep 25, 2009 at 20:32 UTC
    eval "${pack}->function()";

    Why not just

    $pack->function();
      Uh . . yeah =) I guess I thought that only worked with a blessedref, not if the scalar actually just contained the name of the package. While playing with this I also discovered you can do
      $pack->$method
      If the name of the method is in a scalar. However . . what if I want to construct the name of the method?
      $pack = "derived"; $method = "function";
      but say I want to invoke "function2" . . I could say
      $method = "function2"; $path->$method
      But could it be done in one line? Something like . .
      $pack->"${method}2"(); # <-- doesnt compile
        There's always some way to do it! :)
        $pack->can("${method}2")->()
        {grin}

        -- Randal L. Schwartz, Perl hacker

        The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

         $pack->"${method}2"(); # <-- doesnt compile

        Even Perl's syntax has its limits...  :)

        But you could do (if you really can't resist):

        $pack->${\($method."2")};
        This is basically just idle curiosity, but is there any way that the approaches of either almut's Re^3: symbolic reference + inheritance or merlyn's Re^3: symbolic reference + inheritance can be tortured into passing both the invoking class and method arguments into the method upon invocation? (Both of the invocations after the  no strict 'refs'; statement have the same effect, but as the code stands, only one will actually get a chance to run.)
        >perl -wMstrict -le "package base; sub func { print q{in }, __PACKAGE__, qq{ via $_[0] got $_[1]}; } package derived; our @ISA = qw(base); package main; my $pack = 'derived'; $pack ->func(42); 'derived'->func(42); my $foo = 'fu'; $pack->can(qq{${foo}nc})->(42); no strict 'refs'; &{ $pack->${\qq{${foo}nc}} }(42); $pack->${\qq{${foo}nc}}->(42); " in base via derived got 42 in base via derived got 42 Use of uninitialized value in concatenation (.) or string at ... in base via 42 got Use of uninitialized value in concatenation (.) or string at ... in base via derived got Undefined subroutine &main::1 called at -e line 1.