in reply to Need help with a conceptual speed bump

We're talking about symbolic references here

Yes and no.

Yes, Perl looks up methods in the symbol table when you dispatch to them.

No, it does this for methods anyway. If you write a small test program:

use CGI; my $q = CGI->new(); my $new = 'new'; my $z = CGI->$new();

and dump the optree:

$ perl -MO=Concise method_dispatch.pl l <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 514 method_dispatch.pl:8) v/2 ->3 8 <2> sassign vKS/2 ->9 6 <1> entersub[t2] sKS/TARG,2 ->7 3 <0> pushmark s ->4 4 <$> const(PV "CGI") sM/BARE ->5 5 <$> method_named(PVIV "new") s ->6 7 <0> padsv[$q:514,517] sRM*/LVINTRO ->8 9 <;> nextstate(main 515 method_dispatch.pl:9) v/2 ->a c <2> sassign vKS/2 ->d a <$> const(PV "new") s ->b b <0> padsv[$new:515,517] sRM*/LVINTRO ->c d <;> nextstate(main 516 method_dispatch.pl:10) v/2 ->e k <2> sassign vKS/2 ->l i <1> entersub[t5] sKS/TARG,2 ->j e <0> pushmark s ->f f <$> const(PV "CGI") sM/BARE ->g h <1> method sK/1 ->i g <0> padsv[$new:515,517] s ->h j <0> padsv[$z:516,517] sRM*/LVINTRO ->k method_dispatch.pl syntax OK

you'll see that the effective difference is in the method_named and method ops. Looking in pp_hot.c, the former calls method_common with the SV containing the name of the method. The latter checks that the child SV is a reference and returns it if so or calls method_common otherwise.

method_common looks up the method in the appropriate stash and returns the reference.

Is there a difference? I don't really see one. Besides all this, Perl doesn't (and often can't) resolve the target of method calls statically anyway. (There might be some post hoc ergo propter hoc somewhere in all of this.)

Replies are listed 'Best First'.
Re^2: Need help with a conceptual speed bump
by mstone (Deacon) on May 03, 2005 at 23:22 UTC

    Hmm.. that's true, but this:

    $n =1; $ref = "n"; $$ref = 2;

    Gives us a dump that looks like so:

    g <@> leave[1 ref] vKP/REFC ->(end) 1 <0> enter ->2 2 <;> nextstate(main 1 sym.pl:1) v ->3 5 <2> sassign vKS/2 ->6 3 <$> const[IV 1] s ->4 - <1> ex-rv2sv sKRM*/1 ->5 4 <#> gvsv[*n] s ->5 6 <;> nextstate(main 1 sym.pl:2) v ->7 9 <2> sassign vKS/2 ->a 7 <$> const[PV "n"] s ->8 - <1> ex-rv2sv sKRM*/1 ->9 8 <#> gvsv[*ref] s ->9 a <;> nextstate(main 1 sym.pl:3) v ->b f <2> sassign vKS/2 ->g b <$> const[IV 2] s ->c e <1> rv2sv sKRM*/1 ->f d <1> rv2sv sKM/DREFSV,1 ->e c <#> gv[*ref] s ->d

    The difference doesn't appear to be large there, either. This time the switch is between ex-rv2sv / rv2sv and gvsv / gv. I don't have a copy of the perl source at hand, but I'd imagine the behavior is much the same as in method and method_named. The problems are similar, after all.

    The point is, that little bit of indirection occurs in a place where things can go blooey with frightening ease. Imagine code that took the method name as a function parameter instead of looking it up in a statically-defined list. Yucko. Granted, Perl won't auto-vivify functions or clobber a function definition because of a typo, so this is less dangerous than using symrefs for lvalues, but the general mechanism can still be used to do some horribly ugly things.

    Still, you've tipped the scale a bit further in the "less dangerous than flossing with a loaded shotgun" direction, so thanks for your time.

      Good point about global variables. I do think that the difference being that functions aren't writeable (at least as you're using them here) is the important point though.