in reply to symbolic reference + inheritance

eval "${pack}->function()";

Why not just

$pack->function();

Replies are listed 'Best First'.
Re^2: symbolic reference + inheritance
by toddfreed (Novice) on Sep 25, 2009 at 20:57 UTC
    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")};
        Ahh of course. How perfectly arcane.
      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.
        Sure. You can do either of:
        my $meth = $pack->can("${method}2"); $pack->$meth(@args);
        or more simply, if you can give the object twice:
        $pack->can("${method}2")->($pack, @args);

        -- 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.

        ...can be tortured into passing both the invoking class and method arguments

        No torturing required... just omit the arrow :)

        #!/usr/bin/perl -wl use strict; package base; sub func { print q{in }, __PACKAGE__, qq{ via $_[0] got $_[1]}; } package derived; our @ISA = qw(base); package main; my $pack = 'derived'; my $foo = 'fu'; $pack->${\qq{${foo}nc}}(42); __END__ in base via derived got 42


        Update: When you write

        $pack->${\qq{${foo}nc}}->(42);

        you're trying to call a subroutine named like what's returned by func() (here 1, the return value of the print) ...

        Anyhow, some related food for thought:

        #!/usr/bin/perl use strict; use warnings; *{main::1} = sub { print "1() called with args: @_\n" }; main::1(42); # 1() called with args: 42 main::1->(42); # 1() called with args: 42 1->(42); # 1() called with args: 42 main->${\1}(42); # 1() called with args: main 42 no strict 'refs'; main->${\1}->(42); # 1() called with args: main # 1() called with args: 42

        (I particularly like the 1->(42) :)